Chain parameters from Lethean C++ source. Base58 address encoding with Keccak-256 checksum. CryptoNote varint. LWMA difficulty skeleton. Co-Authored-By: Charon <charon@lethean.io>
75 lines
2.3 KiB
Go
75 lines
2.3 KiB
Go
// Copyright (c) 2017-2026 Lethean (https://lt.hn)
|
|
//
|
|
// Licensed under the European Union Public Licence (EUPL) version 1.2.
|
|
// You may obtain a copy of the licence at:
|
|
//
|
|
// https://joinup.ec.europa.eu/software/page/eupl/licence-eupl
|
|
//
|
|
// SPDX-License-Identifier: EUPL-1.2
|
|
|
|
// Package wire provides binary serialisation primitives for the CryptoNote
|
|
// wire protocol. All encoding is consensus-critical and must be bit-identical
|
|
// to the C++ reference implementation.
|
|
package wire
|
|
|
|
import (
|
|
"errors"
|
|
)
|
|
|
|
// MaxVarintLen is the maximum number of bytes a CryptoNote varint can occupy.
|
|
// A uint64 requires at most 10 bytes of 7-bit encoding (64 bits / 7 = ~9.14,
|
|
// so values above 2^63-1 need a 10th byte).
|
|
const MaxVarintLen = 10
|
|
|
|
// ErrVarintOverflow is returned when a varint exceeds the maximum allowed
|
|
// length of 10 bytes.
|
|
var ErrVarintOverflow = errors.New("wire: varint overflow (exceeds 10 bytes)")
|
|
|
|
// ErrVarintEmpty is returned when attempting to decode a varint from an
|
|
// empty byte slice.
|
|
var ErrVarintEmpty = errors.New("wire: cannot decode varint from empty data")
|
|
|
|
// EncodeVarint encodes a uint64 value as a CryptoNote variable-length integer.
|
|
//
|
|
// The encoding uses 7 bits per byte, with the most significant bit (MSB) set
|
|
// to 1 to indicate that more bytes follow. This is the same scheme as protobuf
|
|
// varints but limited to 9 bytes maximum for uint64 values.
|
|
func EncodeVarint(v uint64) []byte {
|
|
if v == 0 {
|
|
return []byte{0x00}
|
|
}
|
|
var buf [MaxVarintLen]byte
|
|
n := 0
|
|
for v > 0 {
|
|
buf[n] = byte(v & 0x7f)
|
|
v >>= 7
|
|
if v > 0 {
|
|
buf[n] |= 0x80
|
|
}
|
|
n++
|
|
}
|
|
return append([]byte(nil), buf[:n]...)
|
|
}
|
|
|
|
// DecodeVarint decodes a CryptoNote variable-length integer from the given
|
|
// byte slice. It returns the decoded value, the number of bytes consumed,
|
|
// and any error encountered.
|
|
func DecodeVarint(data []byte) (uint64, int, error) {
|
|
if len(data) == 0 {
|
|
return 0, 0, ErrVarintEmpty
|
|
}
|
|
var v uint64
|
|
for i := 0; i < len(data) && i < MaxVarintLen; i++ {
|
|
v |= uint64(data[i]&0x7f) << (7 * uint(i))
|
|
if data[i]&0x80 == 0 {
|
|
return v, i + 1, nil
|
|
}
|
|
}
|
|
// If we read MaxVarintLen bytes and the last one still has the
|
|
// continuation bit set, or if we ran out of data with the continuation
|
|
// bit still set, that is an overflow.
|
|
if len(data) >= MaxVarintLen {
|
|
return 0, 0, ErrVarintOverflow
|
|
}
|
|
return 0, 0, ErrVarintOverflow
|
|
}
|