refactor(node): AX error names and levin protocol cleanup
All checks were successful
Security Scan / security (push) Successful in 8s
Test / test (push) Successful in 1m26s

Co-Authored-By: Virgil <virgil@lethean.io>
This commit is contained in:
Snider 2026-03-30 20:44:42 +01:00
commit 51b3cf120b
12 changed files with 180 additions and 108 deletions

View file

@ -118,7 +118,7 @@ func (c *Controller) sendRequest(peerID string, msg *Message, timeout time.Durat
func (c *Controller) GetRemoteStats(peerID string) (*StatsPayload, error) {
identity := c.node.GetIdentity()
if identity == nil {
return nil, ErrIdentityNotInitialized
return nil, ErrorIdentityNotInitialized
}
msg, err := NewMessage(MsgGetStats, identity.ID, peerID, nil)
@ -143,7 +143,7 @@ func (c *Controller) GetRemoteStats(peerID string) (*StatsPayload, error) {
func (c *Controller) StartRemoteMiner(peerID, minerType, profileID string, configOverride RawMessage) error {
identity := c.node.GetIdentity()
if identity == nil {
return ErrIdentityNotInitialized
return ErrorIdentityNotInitialized
}
if minerType == "" {
@ -182,7 +182,7 @@ func (c *Controller) StartRemoteMiner(peerID, minerType, profileID string, confi
func (c *Controller) StopRemoteMiner(peerID, minerName string) error {
identity := c.node.GetIdentity()
if identity == nil {
return ErrIdentityNotInitialized
return ErrorIdentityNotInitialized
}
payload := StopMinerPayload{
@ -215,7 +215,7 @@ func (c *Controller) StopRemoteMiner(peerID, minerName string) error {
func (c *Controller) GetRemoteLogs(peerID, minerName string, lines int) ([]string, error) {
identity := c.node.GetIdentity()
if identity == nil {
return nil, ErrIdentityNotInitialized
return nil, ErrorIdentityNotInitialized
}
payload := GetLogsPayload{
@ -274,7 +274,7 @@ func (c *Controller) GetAllStats() map[string]*StatsPayload {
func (c *Controller) PingPeer(peerID string) (float64, error) {
identity := c.node.GetIdentity()
if identity == nil {
return 0, ErrIdentityNotInitialized
return 0, ErrorIdentityNotInitialized
}
sentAt := time.Now()

View file

@ -100,16 +100,16 @@ func (d *Dispatcher) Handlers() iter.Seq2[byte, IntentHandler] {
// and then to the appropriate intent handler.
//
// Behaviour:
// - Returns ErrThreatScoreExceeded if the packet's ThreatScore exceeds the
// - Returns ErrorThreatScoreExceeded if the packet's ThreatScore exceeds the
// threshold (packet is dropped and logged).
// - Returns ErrUnknownIntent if no handler is registered for the IntentID
// - Returns ErrorUnknownIntent if no handler is registered for the IntentID
// (packet is dropped and logged).
// - Returns nil on successful delivery to a handler, or any error the
// handler itself returns.
// - A nil packet returns ErrNilPacket immediately.
// - A nil packet returns ErrorNilPacket immediately.
func (d *Dispatcher) Dispatch(pkt *ueps.ParsedPacket) error {
if pkt == nil {
return ErrNilPacket
return ErrorNilPacket
}
// 1. Threat circuit breaker (L5 guard)
@ -120,7 +120,7 @@ func (d *Dispatcher) Dispatch(pkt *ueps.ParsedPacket) error {
"intent_id": core.Sprintf("0x%02X", pkt.Header.IntentID),
"version": pkt.Header.Version,
})
return ErrThreatScoreExceeded
return ErrorThreatScoreExceeded
}
// 2. Intent routing (L9 semantic)
@ -133,7 +133,7 @@ func (d *Dispatcher) Dispatch(pkt *ueps.ParsedPacket) error {
"intent_id": core.Sprintf("0x%02X", pkt.Header.IntentID),
"version": pkt.Header.Version,
})
return ErrUnknownIntent
return ErrorUnknownIntent
}
return handler(pkt)
@ -141,14 +141,23 @@ func (d *Dispatcher) Dispatch(pkt *ueps.ParsedPacket) error {
// Sentinel errors returned by Dispatch.
var (
// ErrThreatScoreExceeded is returned when a packet's ThreatScore exceeds
// ErrorThreatScoreExceeded is returned when a packet's ThreatScore exceeds
// the safety threshold.
ErrThreatScoreExceeded = core.E("Dispatcher.Dispatch", core.Sprintf("packet rejected: threat score exceeds safety threshold (%d)", ThreatScoreThreshold), nil)
ErrorThreatScoreExceeded = core.E("Dispatcher.Dispatch", core.Sprintf("packet rejected: threat score exceeds safety threshold (%d)", ThreatScoreThreshold), nil)
// ErrUnknownIntent is returned when no handler is registered for the
// Deprecated: use ErrorThreatScoreExceeded.
ErrThreatScoreExceeded = ErrorThreatScoreExceeded
// ErrorUnknownIntent is returned when no handler is registered for the
// packet's IntentID.
ErrUnknownIntent = core.E("Dispatcher.Dispatch", "packet dropped: unknown intent", nil)
ErrorUnknownIntent = core.E("Dispatcher.Dispatch", "packet dropped: unknown intent", nil)
// ErrNilPacket is returned when a nil packet is passed to Dispatch.
ErrNilPacket = core.E("Dispatcher.Dispatch", "nil packet", nil)
// Deprecated: use ErrorUnknownIntent.
ErrUnknownIntent = ErrorUnknownIntent
// ErrorNilPacket is returned when a nil packet is passed to Dispatch.
ErrorNilPacket = core.E("Dispatcher.Dispatch", "nil packet", nil)
// Deprecated: use ErrorNilPacket.
ErrNilPacket = ErrorNilPacket
)

View file

@ -2,13 +2,19 @@ package node
import core "dappco.re/go/core"
// Sentinel errors shared across the node package.
// Shared error sentinels for the node package.
var (
// ErrIdentityNotInitialized is returned when a node operation requires
// ErrorIdentityNotInitialized is returned when a node operation requires
// a node identity but none has been generated or loaded.
ErrIdentityNotInitialized = core.E("node", "node identity not initialized", nil)
ErrorIdentityNotInitialized = core.E("node", "node identity not initialized", nil)
// ErrMinerManagerNotConfigured is returned when a miner operation is
// Deprecated: use ErrorIdentityNotInitialized.
ErrIdentityNotInitialized = ErrorIdentityNotInitialized
// ErrorMinerManagerNotConfigured is returned when a miner operation is
// attempted but no MinerManager has been set on the Worker.
ErrMinerManagerNotConfigured = core.E("node", "miner manager not configured", nil)
ErrorMinerManagerNotConfigured = core.E("node", "miner manager not configured", nil)
// Deprecated: use ErrorMinerManagerNotConfigured.
ErrMinerManagerNotConfigured = ErrorMinerManagerNotConfigured
)

View file

@ -191,7 +191,7 @@ func (n *NodeManager) DeriveSharedSecret(peerPubKeyBase64 string) ([]byte, error
defer n.mu.RUnlock()
if n.privateKey == nil {
return nil, ErrIdentityNotInitialized
return nil, ErrorIdentityNotInitialized
}
// Load peer's public key

View file

@ -131,7 +131,7 @@ func (c *Connection) ReadPacket() (Header, []byte, error) {
// Check against the connection-specific payload limit.
if h.PayloadSize > c.MaxPayloadSize {
return Header{}, nil, ErrPayloadTooBig
return Header{}, nil, ErrorPayloadTooBig
}
// Empty payload is valid — return nil data without allocation.

View file

@ -22,10 +22,19 @@ const MaxPayloadSize uint64 = 100 * 1024 * 1024
// Return-code constants carried in every Levin response.
const (
ReturnOK int32 = 0
ReturnErrConnection int32 = -1
ReturnErrFormat int32 = -7
ReturnErrSignature int32 = -13
ReturnOK int32 = 0
ReturnErrorConnection int32 = -1
ReturnErrorFormat int32 = -7
ReturnErrorSignature int32 = -13
// Deprecated: use ReturnErrorConnection.
ReturnErrConnection = ReturnErrorConnection
// Deprecated: use ReturnErrorFormat.
ReturnErrFormat = ReturnErrorFormat
// Deprecated: use ReturnErrorSignature.
ReturnErrSignature = ReturnErrorSignature
)
// Command IDs for the CryptoNote P2P layer.
@ -43,8 +52,14 @@ const (
// Sentinel errors returned by DecodeHeader.
var (
ErrBadSignature = core.E("levin", "bad signature", nil)
ErrPayloadTooBig = core.E("levin", "payload exceeds maximum size", nil)
ErrorBadSignature = core.E("levin", "bad signature", nil)
ErrorPayloadTooBig = core.E("levin", "payload exceeds maximum size", nil)
// Deprecated: use ErrorBadSignature.
ErrBadSignature = ErrorBadSignature
// Deprecated: use ErrorPayloadTooBig.
ErrPayloadTooBig = ErrorPayloadTooBig
)
// Header is the 33-byte packed header that prefixes every Levin message.
@ -87,11 +102,11 @@ func DecodeHeader(buf [HeaderSize]byte) (Header, error) {
var h Header
h.Signature = binary.LittleEndian.Uint64(buf[0:8])
if h.Signature != Signature {
return Header{}, ErrBadSignature
return Header{}, ErrorBadSignature
}
h.PayloadSize = binary.LittleEndian.Uint64(buf[8:16])
if h.PayloadSize > MaxPayloadSize {
return Header{}, ErrPayloadTooBig
return Header{}, ErrorPayloadTooBig
}
h.ExpectResponse = buf[16] == 0x01
h.Command = binary.LittleEndian.Uint32(buf[17:21])

View file

@ -40,12 +40,30 @@ const (
// Sentinel errors for storage encoding and decoding.
var (
ErrStorageBadSignature = core.E("levin.storage", "bad storage signature", nil)
ErrStorageTruncated = core.E("levin.storage", "truncated storage data", nil)
ErrStorageBadVersion = core.E("levin.storage", "unsupported storage version", nil)
ErrStorageNameTooLong = core.E("levin.storage", "entry name exceeds 255 bytes", nil)
ErrStorageTypeMismatch = core.E("levin.storage", "value type mismatch", nil)
ErrStorageUnknownType = core.E("levin.storage", "unknown type tag", nil)
ErrorStorageBadSignature = core.E("levin.storage", "bad storage signature", nil)
ErrorStorageTruncated = core.E("levin.storage", "truncated storage data", nil)
ErrorStorageBadVersion = core.E("levin.storage", "unsupported storage version", nil)
ErrorStorageNameTooLong = core.E("levin.storage", "entry name exceeds 255 bytes", nil)
ErrorStorageTypeMismatch = core.E("levin.storage", "value type mismatch", nil)
ErrorStorageUnknownType = core.E("levin.storage", "unknown type tag", nil)
// Deprecated: use ErrorStorageBadSignature.
ErrStorageBadSignature = ErrorStorageBadSignature
// Deprecated: use ErrorStorageTruncated.
ErrStorageTruncated = ErrorStorageTruncated
// Deprecated: use ErrorStorageBadVersion.
ErrStorageBadVersion = ErrorStorageBadVersion
// Deprecated: use ErrorStorageNameTooLong.
ErrStorageNameTooLong = ErrorStorageNameTooLong
// Deprecated: use ErrorStorageTypeMismatch.
ErrStorageTypeMismatch = ErrorStorageTypeMismatch
// Deprecated: use ErrorStorageUnknownType.
ErrStorageUnknownType = ErrorStorageUnknownType
)
// Section is an ordered map of named values forming a portable storage section.
@ -179,7 +197,7 @@ func ObjectArrayVal(vs []Section) Value {
// AsUint64 returns the uint64 value or an error on type mismatch.
func (v Value) AsUint64() (uint64, error) {
if v.Type != TypeUint64 {
return 0, ErrStorageTypeMismatch
return 0, ErrorStorageTypeMismatch
}
return v.uintVal, nil
}
@ -187,7 +205,7 @@ func (v Value) AsUint64() (uint64, error) {
// AsUint32 returns the uint32 value or an error on type mismatch.
func (v Value) AsUint32() (uint32, error) {
if v.Type != TypeUint32 {
return 0, ErrStorageTypeMismatch
return 0, ErrorStorageTypeMismatch
}
return uint32(v.uintVal), nil
}
@ -195,7 +213,7 @@ func (v Value) AsUint32() (uint32, error) {
// AsUint16 returns the uint16 value or an error on type mismatch.
func (v Value) AsUint16() (uint16, error) {
if v.Type != TypeUint16 {
return 0, ErrStorageTypeMismatch
return 0, ErrorStorageTypeMismatch
}
return uint16(v.uintVal), nil
}
@ -203,7 +221,7 @@ func (v Value) AsUint16() (uint16, error) {
// AsUint8 returns the uint8 value or an error on type mismatch.
func (v Value) AsUint8() (uint8, error) {
if v.Type != TypeUint8 {
return 0, ErrStorageTypeMismatch
return 0, ErrorStorageTypeMismatch
}
return uint8(v.uintVal), nil
}
@ -211,7 +229,7 @@ func (v Value) AsUint8() (uint8, error) {
// AsInt64 returns the int64 value or an error on type mismatch.
func (v Value) AsInt64() (int64, error) {
if v.Type != TypeInt64 {
return 0, ErrStorageTypeMismatch
return 0, ErrorStorageTypeMismatch
}
return v.intVal, nil
}
@ -219,7 +237,7 @@ func (v Value) AsInt64() (int64, error) {
// AsInt32 returns the int32 value or an error on type mismatch.
func (v Value) AsInt32() (int32, error) {
if v.Type != TypeInt32 {
return 0, ErrStorageTypeMismatch
return 0, ErrorStorageTypeMismatch
}
return int32(v.intVal), nil
}
@ -227,7 +245,7 @@ func (v Value) AsInt32() (int32, error) {
// AsInt16 returns the int16 value or an error on type mismatch.
func (v Value) AsInt16() (int16, error) {
if v.Type != TypeInt16 {
return 0, ErrStorageTypeMismatch
return 0, ErrorStorageTypeMismatch
}
return int16(v.intVal), nil
}
@ -235,7 +253,7 @@ func (v Value) AsInt16() (int16, error) {
// AsInt8 returns the int8 value or an error on type mismatch.
func (v Value) AsInt8() (int8, error) {
if v.Type != TypeInt8 {
return 0, ErrStorageTypeMismatch
return 0, ErrorStorageTypeMismatch
}
return int8(v.intVal), nil
}
@ -243,7 +261,7 @@ func (v Value) AsInt8() (int8, error) {
// AsBool returns the bool value or an error on type mismatch.
func (v Value) AsBool() (bool, error) {
if v.Type != TypeBool {
return false, ErrStorageTypeMismatch
return false, ErrorStorageTypeMismatch
}
return v.boolVal, nil
}
@ -251,7 +269,7 @@ func (v Value) AsBool() (bool, error) {
// AsDouble returns the float64 value or an error on type mismatch.
func (v Value) AsDouble() (float64, error) {
if v.Type != TypeDouble {
return 0, ErrStorageTypeMismatch
return 0, ErrorStorageTypeMismatch
}
return v.floatVal, nil
}
@ -259,7 +277,7 @@ func (v Value) AsDouble() (float64, error) {
// AsString returns the byte-string value or an error on type mismatch.
func (v Value) AsString() ([]byte, error) {
if v.Type != TypeString {
return nil, ErrStorageTypeMismatch
return nil, ErrorStorageTypeMismatch
}
return v.bytesVal, nil
}
@ -267,7 +285,7 @@ func (v Value) AsString() ([]byte, error) {
// AsSection returns the nested Section or an error on type mismatch.
func (v Value) AsSection() (Section, error) {
if v.Type != TypeObject {
return nil, ErrStorageTypeMismatch
return nil, ErrorStorageTypeMismatch
}
return v.objectVal, nil
}
@ -279,7 +297,7 @@ func (v Value) AsSection() (Section, error) {
// AsUint64Array returns the []uint64 array or an error on type mismatch.
func (v Value) AsUint64Array() ([]uint64, error) {
if v.Type != (ArrayFlag | TypeUint64) {
return nil, ErrStorageTypeMismatch
return nil, ErrorStorageTypeMismatch
}
return v.uint64Array, nil
}
@ -287,7 +305,7 @@ func (v Value) AsUint64Array() ([]uint64, error) {
// AsUint32Array returns the []uint32 array or an error on type mismatch.
func (v Value) AsUint32Array() ([]uint32, error) {
if v.Type != (ArrayFlag | TypeUint32) {
return nil, ErrStorageTypeMismatch
return nil, ErrorStorageTypeMismatch
}
return v.uint32Array, nil
}
@ -295,7 +313,7 @@ func (v Value) AsUint32Array() ([]uint32, error) {
// AsStringArray returns the [][]byte array or an error on type mismatch.
func (v Value) AsStringArray() ([][]byte, error) {
if v.Type != (ArrayFlag | TypeString) {
return nil, ErrStorageTypeMismatch
return nil, ErrorStorageTypeMismatch
}
return v.stringArray, nil
}
@ -303,7 +321,7 @@ func (v Value) AsStringArray() ([][]byte, error) {
// AsSectionArray returns the []Section array or an error on type mismatch.
func (v Value) AsSectionArray() ([]Section, error) {
if v.Type != (ArrayFlag | TypeObject) {
return nil, ErrStorageTypeMismatch
return nil, ErrorStorageTypeMismatch
}
return v.objectArray, nil
}
@ -348,7 +366,7 @@ func encodeSection(buf []byte, s Section) ([]byte, error) {
// Name: uint8 length + raw bytes.
if len(name) > 255 {
return nil, ErrStorageNameTooLong
return nil, ErrorStorageNameTooLong
}
buf = append(buf, byte(len(name)))
buf = append(buf, name...)
@ -431,7 +449,7 @@ func encodeValue(buf []byte, v Value) ([]byte, error) {
return encodeSection(buf, v.objectVal)
default:
return nil, core.E("levin.encodeValue", core.Sprintf("unknown type tag: 0x%02x", v.Type), ErrStorageUnknownType)
return nil, core.E("levin.encodeValue", core.Sprintf("unknown type tag: 0x%02x", v.Type), ErrorStorageUnknownType)
}
}
@ -478,7 +496,7 @@ func encodeArray(buf []byte, v Value) ([]byte, error) {
return buf, nil
default:
return nil, core.E("levin.encodeArray", core.Sprintf("unknown type tag: array of 0x%02x", elemType), ErrStorageUnknownType)
return nil, core.E("levin.encodeArray", core.Sprintf("unknown type tag: array of 0x%02x", elemType), ErrorStorageUnknownType)
}
}
@ -492,7 +510,7 @@ func encodeArray(buf []byte, v Value) ([]byte, error) {
// section, err := DecodeStorage(data)
func DecodeStorage(data []byte) (Section, error) {
if len(data) < StorageHeaderSize {
return nil, ErrStorageTruncated
return nil, ErrorStorageTruncated
}
sigA := binary.LittleEndian.Uint32(data[0:4])
@ -500,10 +518,10 @@ func DecodeStorage(data []byte) (Section, error) {
ver := data[8]
if sigA != StorageSignatureA || sigB != StorageSignatureB {
return nil, ErrStorageBadSignature
return nil, ErrorStorageBadSignature
}
if ver != StorageVersion {
return nil, ErrStorageBadVersion
return nil, ErrorStorageBadVersion
}
s, _, err := decodeSection(data[StorageHeaderSize:])
@ -524,21 +542,21 @@ func decodeSection(buf []byte) (Section, int, error) {
for range count {
// Name length (1 byte).
if off >= len(buf) {
return nil, 0, ErrStorageTruncated
return nil, 0, ErrorStorageTruncated
}
nameLen := int(buf[off])
off++
// Name bytes.
if off+nameLen > len(buf) {
return nil, 0, ErrStorageTruncated
return nil, 0, ErrorStorageTruncated
}
name := string(buf[off : off+nameLen])
off += nameLen
// Type tag (1 byte).
if off >= len(buf) {
return nil, 0, ErrStorageTruncated
return nil, 0, ErrorStorageTruncated
}
tag := buf[off]
off++
@ -567,68 +585,68 @@ func decodeValue(buf []byte, tag uint8) (Value, int, error) {
switch tag {
case TypeUint64:
if len(buf) < 8 {
return Value{}, 0, ErrStorageTruncated
return Value{}, 0, ErrorStorageTruncated
}
v := binary.LittleEndian.Uint64(buf[:8])
return Value{Type: TypeUint64, uintVal: v}, 8, nil
case TypeInt64:
if len(buf) < 8 {
return Value{}, 0, ErrStorageTruncated
return Value{}, 0, ErrorStorageTruncated
}
v := int64(binary.LittleEndian.Uint64(buf[:8]))
return Value{Type: TypeInt64, intVal: v}, 8, nil
case TypeDouble:
if len(buf) < 8 {
return Value{}, 0, ErrStorageTruncated
return Value{}, 0, ErrorStorageTruncated
}
bits := binary.LittleEndian.Uint64(buf[:8])
return Value{Type: TypeDouble, floatVal: math.Float64frombits(bits)}, 8, nil
case TypeUint32:
if len(buf) < 4 {
return Value{}, 0, ErrStorageTruncated
return Value{}, 0, ErrorStorageTruncated
}
v := binary.LittleEndian.Uint32(buf[:4])
return Value{Type: TypeUint32, uintVal: uint64(v)}, 4, nil
case TypeInt32:
if len(buf) < 4 {
return Value{}, 0, ErrStorageTruncated
return Value{}, 0, ErrorStorageTruncated
}
v := int32(binary.LittleEndian.Uint32(buf[:4]))
return Value{Type: TypeInt32, intVal: int64(v)}, 4, nil
case TypeUint16:
if len(buf) < 2 {
return Value{}, 0, ErrStorageTruncated
return Value{}, 0, ErrorStorageTruncated
}
v := binary.LittleEndian.Uint16(buf[:2])
return Value{Type: TypeUint16, uintVal: uint64(v)}, 2, nil
case TypeInt16:
if len(buf) < 2 {
return Value{}, 0, ErrStorageTruncated
return Value{}, 0, ErrorStorageTruncated
}
v := int16(binary.LittleEndian.Uint16(buf[:2]))
return Value{Type: TypeInt16, intVal: int64(v)}, 2, nil
case TypeUint8:
if len(buf) < 1 {
return Value{}, 0, ErrStorageTruncated
return Value{}, 0, ErrorStorageTruncated
}
return Value{Type: TypeUint8, uintVal: uint64(buf[0])}, 1, nil
case TypeInt8:
if len(buf) < 1 {
return Value{}, 0, ErrStorageTruncated
return Value{}, 0, ErrorStorageTruncated
}
return Value{Type: TypeInt8, intVal: int64(int8(buf[0]))}, 1, nil
case TypeBool:
if len(buf) < 1 {
return Value{}, 0, ErrStorageTruncated
return Value{}, 0, ErrorStorageTruncated
}
return Value{Type: TypeBool, boolVal: buf[0] != 0}, 1, nil
@ -638,7 +656,7 @@ func decodeValue(buf []byte, tag uint8) (Value, int, error) {
return Value{}, 0, err
}
if uint64(len(buf)-n) < strLen {
return Value{}, 0, ErrStorageTruncated
return Value{}, 0, ErrorStorageTruncated
}
data := make([]byte, strLen)
copy(data, buf[n:n+int(strLen)])
@ -652,7 +670,7 @@ func decodeValue(buf []byte, tag uint8) (Value, int, error) {
return Value{Type: TypeObject, objectVal: sec}, consumed, nil
default:
return Value{}, 0, core.E("levin.decodeValue", core.Sprintf("unknown type tag: 0x%02x", tag), ErrStorageUnknownType)
return Value{}, 0, core.E("levin.decodeValue", core.Sprintf("unknown type tag: 0x%02x", tag), ErrorStorageUnknownType)
}
}
@ -671,7 +689,7 @@ func decodeArray(buf []byte, tag uint8) (Value, int, error) {
arr := make([]uint64, count)
for i := range count {
if off+8 > len(buf) {
return Value{}, 0, ErrStorageTruncated
return Value{}, 0, ErrorStorageTruncated
}
arr[i] = binary.LittleEndian.Uint64(buf[off : off+8])
off += 8
@ -682,7 +700,7 @@ func decodeArray(buf []byte, tag uint8) (Value, int, error) {
arr := make([]uint32, count)
for i := range count {
if off+4 > len(buf) {
return Value{}, 0, ErrStorageTruncated
return Value{}, 0, ErrorStorageTruncated
}
arr[i] = binary.LittleEndian.Uint32(buf[off : off+4])
off += 4
@ -698,7 +716,7 @@ func decodeArray(buf []byte, tag uint8) (Value, int, error) {
}
off += sn
if uint64(len(buf)-off) < strLen {
return Value{}, 0, ErrStorageTruncated
return Value{}, 0, ErrorStorageTruncated
}
data := make([]byte, strLen)
copy(data, buf[off:off+int(strLen)])
@ -720,6 +738,6 @@ func decodeArray(buf []byte, tag uint8) (Value, int, error) {
return Value{Type: tag, objectArray: arr}, off, nil
default:
return Value{}, 0, core.E("levin.decodeArray", core.Sprintf("unknown type tag: array of 0x%02x", elemType), ErrStorageUnknownType)
return Value{}, 0, core.E("levin.decodeArray", core.Sprintf("unknown type tag: array of 0x%02x", elemType), ErrorStorageUnknownType)
}
}

View file

@ -22,11 +22,17 @@ const (
varintMax8 = 4_611_686_018_427_387_903
)
// ErrVarintTruncated is returned when the buffer is too short.
var ErrVarintTruncated = core.E("levin", "truncated varint", nil)
// ErrorVarintTruncated is returned when the buffer is too short.
var ErrorVarintTruncated = core.E("levin", "truncated varint", nil)
// ErrVarintOverflow is returned when the value is too large to encode.
var ErrVarintOverflow = core.E("levin", "varint overflow", nil)
// Deprecated: use ErrorVarintTruncated.
var ErrVarintTruncated = ErrorVarintTruncated
// ErrorVarintOverflow is returned when the value is too large to encode.
var ErrorVarintOverflow = core.E("levin", "varint overflow", nil)
// Deprecated: use ErrorVarintOverflow.
var ErrVarintOverflow = ErrorVarintOverflow
// PackVarint encodes v using the epee portable-storage varint scheme.
// The low two bits of the first byte indicate the total encoded width;
@ -61,7 +67,7 @@ func PackVarint(v uint64) []byte {
// value, err := UnpackVarint(data)
func UnpackVarint(buf []byte) (value uint64, bytesConsumed int, err error) {
if len(buf) == 0 {
return 0, 0, ErrVarintTruncated
return 0, 0, ErrorVarintTruncated
}
mark := buf[0] & varintMask
@ -72,27 +78,27 @@ func UnpackVarint(buf []byte) (value uint64, bytesConsumed int, err error) {
return value, 1, nil
case varintMark2:
if len(buf) < 2 {
return 0, 0, ErrVarintTruncated
return 0, 0, ErrorVarintTruncated
}
raw := binary.LittleEndian.Uint16(buf[:2])
value = uint64(raw) >> 2
return value, 2, nil
case varintMark4:
if len(buf) < 4 {
return 0, 0, ErrVarintTruncated
return 0, 0, ErrorVarintTruncated
}
raw := binary.LittleEndian.Uint32(buf[:4])
value = uint64(raw) >> 2
return value, 4, nil
case varintMark8:
if len(buf) < 8 {
return 0, 0, ErrVarintTruncated
return 0, 0, ErrorVarintTruncated
}
raw := binary.LittleEndian.Uint64(buf[:8])
value = raw >> 2
return value, 8, nil
default:
// Unreachable — mark is masked to 2 bits.
return 0, 0, ErrVarintTruncated
return 0, 0, ErrorVarintTruncated
}
}

View file

@ -8,11 +8,11 @@ import (
"github.com/google/uuid"
)
// Protocol version constants
// Protocol version constants.
const (
// ProtocolVersion is the current protocol version
// ProtocolVersion is the current protocol version.
ProtocolVersion = "1.0"
// MinProtocolVersion is the minimum supported version
// MinProtocolVersion is the minimum supported version.
MinProtocolVersion = "1.0"
)
@ -273,26 +273,44 @@ type DeployAckPayload struct {
// ErrorPayload contains error information.
//
// payload := ErrorPayload{Code: ErrCodeOperationFailed, Message: "start failed"}
// payload := ErrorPayload{Code: ErrorCodeOperationFailed, Message: "start failed"}
type ErrorPayload struct {
Code int `json:"code"`
Message string `json:"message"`
Details string `json:"details,omitempty"`
}
// Common error codes
// Common error codes.
const (
ErrCodeUnknown = 1000
ErrCodeInvalidMessage = 1001
ErrCodeUnauthorized = 1002
ErrCodeNotFound = 1003
ErrCodeOperationFailed = 1004
ErrCodeTimeout = 1005
ErrorCodeUnknown = 1000
ErrorCodeInvalidMessage = 1001
ErrorCodeUnauthorized = 1002
ErrorCodeNotFound = 1003
ErrorCodeOperationFailed = 1004
ErrorCodeTimeout = 1005
// Deprecated: use ErrorCodeUnknown.
ErrCodeUnknown = ErrorCodeUnknown
// Deprecated: use ErrorCodeInvalidMessage.
ErrCodeInvalidMessage = ErrorCodeInvalidMessage
// Deprecated: use ErrorCodeUnauthorized.
ErrCodeUnauthorized = ErrorCodeUnauthorized
// Deprecated: use ErrorCodeNotFound.
ErrCodeNotFound = ErrorCodeNotFound
// Deprecated: use ErrorCodeOperationFailed.
ErrCodeOperationFailed = ErrorCodeOperationFailed
// Deprecated: use ErrorCodeTimeout.
ErrCodeTimeout = ErrorCodeTimeout
)
// NewErrorMessage creates an error response message.
//
// msg, err := NewErrorMessage("worker", "controller", ErrCodeOperationFailed, "miner start failed", "req-1")
// msg, err := NewErrorMessage("worker", "controller", ErrorCodeOperationFailed, "miner start failed", "req-1")
func NewErrorMessage(from, to string, code int, message string, replyTo string) (*Message, error) {
msg, err := NewMessage(MsgError, from, to, ErrorPayload{
Code: code,

View file

@ -6,7 +6,7 @@ import (
// ProtocolError represents an error from the remote peer.
//
// err := &ProtocolError{Code: ErrCodeOperationFailed, Message: "start failed"}
// err := &ProtocolError{Code: ErrorCodeOperationFailed, Message: "start failed"}
type ProtocolError struct {
Code int
Message string
@ -35,7 +35,7 @@ func (h *ResponseHandler) ValidateResponse(resp *Message, expectedType MessageTy
if resp.Type == MsgError {
var errPayload ErrorPayload
if err := resp.ParsePayload(&errPayload); err != nil {
return &ProtocolError{Code: ErrCodeUnknown, Message: "unable to parse error response"}
return &ProtocolError{Code: ErrorCodeUnknown, Message: "unable to parse error response"}
}
return &ProtocolError{Code: errPayload.Code, Message: errPayload.Message}
}

View file

@ -641,7 +641,7 @@ func (t *Transport) performHandshake(pc *PeerConnection) error {
identity := t.node.GetIdentity()
if identity == nil {
return ErrIdentityNotInitialized
return ErrorIdentityNotInitialized
}
// Generate challenge for the server to prove it has the matching private key

View file

@ -103,7 +103,7 @@ func (w *Worker) HandleMessage(conn *PeerConnection, msg *Message) {
errMsg, _ := NewErrorMessage(
identity.ID,
msg.From,
ErrCodeOperationFailed,
ErrorCodeOperationFailed,
err.Error(),
msg.ID,
)
@ -141,7 +141,7 @@ func (w *Worker) handlePing(msg *Message) (*Message, error) {
func (w *Worker) handleGetStats(msg *Message) (*Message, error) {
identity := w.node.GetIdentity()
if identity == nil {
return nil, ErrIdentityNotInitialized
return nil, ErrorIdentityNotInitialized
}
stats := StatsPayload{
@ -204,7 +204,7 @@ func convertMinerStats(miner MinerInstance, rawStats any) MinerStatsItem {
// handleStartMiner starts a miner with the given profile.
func (w *Worker) handleStartMiner(msg *Message) (*Message, error) {
if w.minerManager == nil {
return nil, ErrMinerManagerNotConfigured
return nil, ErrorMinerManagerNotConfigured
}
var payload StartMinerPayload
@ -251,7 +251,7 @@ func (w *Worker) handleStartMiner(msg *Message) (*Message, error) {
// handleStopMiner stops a running miner.
func (w *Worker) handleStopMiner(msg *Message) (*Message, error) {
if w.minerManager == nil {
return nil, ErrMinerManagerNotConfigured
return nil, ErrorMinerManagerNotConfigured
}
var payload StopMinerPayload
@ -274,7 +274,7 @@ func (w *Worker) handleStopMiner(msg *Message) (*Message, error) {
// handleGetLogs returns console logs from a miner.
func (w *Worker) handleGetLogs(msg *Message) (*Message, error) {
if w.minerManager == nil {
return nil, ErrMinerManagerNotConfigured
return nil, ErrorMinerManagerNotConfigured
}
var payload GetLogsPayload