Files
zeekay 7cf87b230b node-unified is the node
The module already called itself github.com/luxfi/node while containing no node
in Go: cmd/luxd was twenty-one lines that printed the size of a few types, and
the Go column of the matrix measured a VM plugin. A repo that fetches the thing
it claims to be has not replaced it, so the Go sources move in — 1515 files,
the daemon and everything under it — and the build reaches outside this module
for nothing.

Rust and C++ sit beside it unchanged and are still measured against it by the
differential. That is the point of one repo: the reference implementation and
the two ports are the same checkout, so parity is a thing you can run rather
than a thing you assert.

Verified: builds, and the closure carries no lux-private — checked at build time
rather than believed. The daemon starts twelve chains on a local network
(P X C Q Z A B G K M F, plus D through its plugin) and reports healthy.
2026-09-07 16:15:25 -07:00

96 lines
3.0 KiB
Go

// Copyright (C) 2019-2025, Lux Industries Inc. All rights reserved.
// See the file LICENSE for licensing terms.
package archivedb
import (
"encoding/binary"
"errors"
"github.com/luxfi/node/utils/wrappers"
)
var (
ErrParsingKeyLength = errors.New("failed reading key length")
ErrIncorrectKeyLength = errors.New("incorrect key length")
heightKey = newDBKeyFromMetadata([]byte{})
)
// The requirements of a database key are:
//
// 1. A given user key must have a unique database key prefix. This guarantees
// that user keys can not overlap on disk.
// 2. Inside of a database key prefix, the database keys must be sorted by
// decreasing height.
// 3. User keys must never overlap with any metadata keys.
// newDBKeyFromUser converts a user key and height into a database formatted
// key.
//
// To meet the requirements of a database key, the prefix is defined by
// concatenating the length of the user key and the user key. The suffix of the
// database key is the negation of the big endian encoded height. This suffix
// guarantees the keys are sorted correctly.
//
// Example (Asumming heights are 1 byte):
// | User key | Stored as |
// |------------|-------------|
// | foo:10 | 3:foo:245 |
// | foo:20 | 3:foo:235 |
//
// Returns:
// - The database key
// - The database key prefix, which is independent of the height
func newDBKeyFromUser(key []byte, height uint64) ([]byte, []byte) {
keyLen := len(key)
dbKeyMaxSize := binary.MaxVarintLen64 + keyLen + wrappers.LongLen
dbKey := make([]byte, dbKeyMaxSize)
offset := binary.PutUvarint(dbKey, uint64(keyLen))
offset += copy(dbKey[offset:], key)
prefixOffset := offset
binary.BigEndian.PutUint64(dbKey[offset:], ^height)
offset += wrappers.LongLen
return dbKey[:offset], dbKey[:prefixOffset]
}
// parseDBKeyFromUser takes a database formatted key and returns the user key
// along with its height.
//
// Note: An error should only be returned from this function if the database has
// been corrupted.
func parseDBKeyFromUser(dbKey []byte) ([]byte, uint64, error) {
keyLen, offset := binary.Uvarint(dbKey)
if offset <= 0 {
return nil, 0, ErrParsingKeyLength
}
heightIndex := uint64(offset) + keyLen
if uint64(len(dbKey)) != heightIndex+wrappers.LongLen {
return nil, 0, ErrIncorrectKeyLength
}
key := dbKey[offset:heightIndex]
height := ^binary.BigEndian.Uint64(dbKey[heightIndex:])
return key, height, nil
}
// newDBKeyFromMetadata converts a metadata key into a database formatted key.
//
// To meet the requirements of a database key, the key is defined by
// concatenating the length of the metadata key + 1 and the metadata key.
//
// Example:
// | Metadata key | Stored as |
// |----------------|-------------|
// | foo | 4:foo |
// | fo | 3:fo |
func newDBKeyFromMetadata(key []byte) []byte {
keyLen := len(key)
dbKeyMaxSize := binary.MaxVarintLen64 + keyLen
dbKey := make([]byte, dbKeyMaxSize)
offset := binary.PutUvarint(dbKey, uint64(keyLen)+1)
offset += copy(dbKey[offset:], key)
return dbKey[:offset]
}