95 lines
2.9 KiB
Go
95 lines
2.9 KiB
Go
// Copyright (c) 2024-2026 Lethean Contributors
|
|
// SPDX-License-Identifier: EUPL-1.2
|
|
|
|
// Package levin implements the CryptoNote Levin binary protocol.
|
|
// It is a standalone package with no imports from the parent node package.
|
|
package levin
|
|
|
|
import (
|
|
"encoding/binary"
|
|
|
|
core "dappco.re/go/core"
|
|
)
|
|
|
|
// headerBytes := make([]byte, HeaderSize)
|
|
const HeaderSize = 33
|
|
|
|
// header.Signature = Signature
|
|
const Signature uint64 = 0x0101010101012101
|
|
|
|
// header.PayloadSize <= MaxPayloadSize
|
|
const MaxPayloadSize uint64 = 100 * 1024 * 1024
|
|
|
|
const (
|
|
// returnCode := ReturnOK
|
|
ReturnOK int32 = 0
|
|
ReturnErrorConnection int32 = -1
|
|
ReturnErrorFormat int32 = -7
|
|
ReturnErrorSignature int32 = -13
|
|
)
|
|
|
|
const (
|
|
// commandID := CommandHandshake
|
|
CommandHandshake uint32 = 1001
|
|
CommandTimedSync uint32 = 1002
|
|
CommandPing uint32 = 1003
|
|
CommandNewBlock uint32 = 2001
|
|
CommandNewTransactions uint32 = 2002
|
|
CommandRequestObjects uint32 = 2003
|
|
CommandResponseObjects uint32 = 2004
|
|
CommandRequestChain uint32 = 2006
|
|
CommandResponseChain uint32 = 2007
|
|
)
|
|
|
|
var (
|
|
// err := ErrorBadSignature
|
|
ErrorBadSignature = core.E("levin", "bad signature", nil)
|
|
ErrorPayloadTooBig = core.E("levin", "payload exceeds maximum size", nil)
|
|
)
|
|
|
|
// header := Header{Command: CommandHandshake, ExpectResponse: true}
|
|
type Header struct {
|
|
Signature uint64
|
|
PayloadSize uint64
|
|
ExpectResponse bool
|
|
Command uint32
|
|
ReturnCode int32
|
|
Flags uint32
|
|
ProtocolVersion uint32
|
|
}
|
|
|
|
// encoded := EncodeHeader(header)
|
|
func EncodeHeader(header *Header) [HeaderSize]byte {
|
|
var headerBytes [HeaderSize]byte
|
|
binary.LittleEndian.PutUint64(headerBytes[0:8], header.Signature)
|
|
binary.LittleEndian.PutUint64(headerBytes[8:16], header.PayloadSize)
|
|
if header.ExpectResponse {
|
|
headerBytes[16] = 0x01
|
|
} else {
|
|
headerBytes[16] = 0x00
|
|
}
|
|
binary.LittleEndian.PutUint32(headerBytes[17:21], header.Command)
|
|
binary.LittleEndian.PutUint32(headerBytes[21:25], uint32(header.ReturnCode))
|
|
binary.LittleEndian.PutUint32(headerBytes[25:29], header.Flags)
|
|
binary.LittleEndian.PutUint32(headerBytes[29:33], header.ProtocolVersion)
|
|
return headerBytes
|
|
}
|
|
|
|
// header, err := DecodeHeader(headerBytes)
|
|
func DecodeHeader(headerBytes [HeaderSize]byte) (Header, error) {
|
|
var header Header
|
|
header.Signature = binary.LittleEndian.Uint64(headerBytes[0:8])
|
|
if header.Signature != Signature {
|
|
return Header{}, ErrorBadSignature
|
|
}
|
|
header.PayloadSize = binary.LittleEndian.Uint64(headerBytes[8:16])
|
|
if header.PayloadSize > MaxPayloadSize {
|
|
return Header{}, ErrorPayloadTooBig
|
|
}
|
|
header.ExpectResponse = headerBytes[16] == 0x01
|
|
header.Command = binary.LittleEndian.Uint32(headerBytes[17:21])
|
|
header.ReturnCode = int32(binary.LittleEndian.Uint32(headerBytes[21:25]))
|
|
header.Flags = binary.LittleEndian.Uint32(headerBytes[25:29])
|
|
header.ProtocolVersion = binary.LittleEndian.Uint32(headerBytes[29:33])
|
|
return header, nil
|
|
}
|