go-p2p/node/levin/header.go
Virgil e3b66f7e8c refactor(node): align remaining AX naming and examples
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-31 15:39:28 +01:00

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
}