package prefixes // The prefixes package contains the key/value structures for the rocksdb prefix // store and related functions. // Each key/value prefix pair has a pack and unpack function for serializing / deserializing // it into bytes for storage in rocksdb. They also have a pack partial function which allows // for serialization of a set number of fields, this is used i.e. for keys with a hash, tx_num // and height where there multiple be multiple with the same hash but different tx_num and height. import ( "bytes" "encoding/binary" "encoding/hex" "fmt" "log" "reflect" "sort" "strings" "github.com/lbryio/herald.go/internal" "github.com/lbryio/lbcd/chaincfg/chainhash" ) const ( ClaimToSupport = 'K' SupportToClaim = 'L' ClaimToTXO = 'E' TXOToClaim = 'G' ClaimToChannel = 'I' ChannelToClaim = 'J' ClaimShortIdPrefix = 'F' BidOrder = 'D' ClaimExpiration = 'O' ClaimTakeover = 'P' PendingActivation = 'Q' ActivatedClaimAndSupport = 'R' ActiveAmount = 'S' Repost = 'V' RepostedClaim = 'W' Undo = 'M' ClaimDiff = 'Y' Tx = 'B' BlockHash = 'C' Header = 'H' TxNum = 'N' TxCount = 'T' TxHash = 'X' UTXO = 'u' HashXUTXO = 'h' HashXHistory = 'x' DBState = 's' ChannelCount = 'Z' SupportAmount = 'a' BlockTXs = 'b' TrendingNotifications = 'c' MempoolTx = 'd' TouchedHashX = 'e' HashXStatus = 'f' HashXMempoolStatus = 'g' EffectiveAmount = 'i' RepostedCount = 'j' ActivateClaimTXOType = 1 ActivatedSupportTXOType = 2 OnesCompTwiddle64 uint64 = 0xffffffffffffffff OnesCompTwiddle32 uint32 = 0xffffffff ) // GetPrefixes returns an array of all the byte prefix constants. func GetPrefixes() [][]byte { return [][]byte{ {ClaimToSupport}, {SupportToClaim}, {ClaimToTXO}, {TXOToClaim}, {ClaimToChannel}, {ChannelToClaim}, {ClaimShortIdPrefix}, {BidOrder}, {ClaimExpiration}, {ClaimTakeover}, {PendingActivation}, {ActivatedClaimAndSupport}, {ActiveAmount}, {Repost}, {RepostedClaim}, {Undo}, {ClaimDiff}, {Tx}, {BlockHash}, {Header}, {TxNum}, {TxCount}, {TxHash}, {UTXO}, {HashXUTXO}, {HashXHistory}, {DBState}, {ChannelCount}, {SupportAmount}, {BlockTXs}, {TrendingNotifications}, {MempoolTx}, {TouchedHashX}, {HashXStatus}, {HashXMempoolStatus}, {EffectiveAmount}, {RepostedCount}, } } // PrefixRowKV is a generic key/value pair for a prefix. type PrefixRowKV struct { Key BaseKey Value BaseValue RawKey []byte RawValue []byte Error error } type BaseKey interface { NumFields() int PartialPack(fields int) []byte PackKey() []byte } type BaseValue interface { PackValue() []byte } type KeyUnpacker interface { UnpackKey(buf []byte) } type ValueUnpacker interface { UnpackValue(buf []byte) } type LengthEncodedName struct { NameLen uint16 `struct:"sizeof=Name"` Name string `json:"name"` } func NewLengthEncodedName(s string) LengthEncodedName { return LengthEncodedName{ NameLen: uint16(len(s)), Name: s, } } type LengthEncodedNormalizedName struct { NormalizedNameLen uint16 `struct:"sizeof=NormalizedName"` NormalizedName string `json:"normalized_name"` } func NewLengthEncodedNormalizedName(s string) LengthEncodedNormalizedName { return LengthEncodedNormalizedName{ NormalizedNameLen: uint16(len(s)), NormalizedName: s, } } type LengthEncodedPartialClaimId struct { PartialClaimIdLen uint8 `struct:"sizeof=PartialClaimId"` PartialClaimId string `json:"partial_claim_id"` } func NewLengthEncodedPartialClaimId(s string) LengthEncodedPartialClaimId { return LengthEncodedPartialClaimId{ PartialClaimIdLen: uint8(len(s)), PartialClaimId: s, } } type DBStateKey struct { Prefix []byte `struct:"[1]byte" json:"prefix"` } type DBStateValue struct { Genesis *chainhash.Hash Height uint32 TxCount uint32 Tip *chainhash.Hash UtxoFlushCount uint32 WallTime uint32 FirstSync bool DBVersion uint8 HistFlushCount int32 CompFlushCount int32 CompCursor int32 EsSyncHeight uint32 } func NewDBStateValue() *DBStateValue { return &DBStateValue{ Genesis: new(chainhash.Hash), Height: 0, TxCount: 0, Tip: new(chainhash.Hash), UtxoFlushCount: 0, WallTime: 0, FirstSync: true, DBVersion: 0, HistFlushCount: 0, CompFlushCount: -1, CompCursor: -1, EsSyncHeight: 0, } } func NewDBStateKey() *DBStateKey { return &DBStateKey{ Prefix: []byte{DBState}, } } func (k *DBStateKey) PackKey() []byte { prefixLen := 1 n := prefixLen key := make([]byte, n) copy(key, k.Prefix) return key } func (v *DBStateValue) PackValue() []byte { // b'>32sLL32sLLBBlllL' n := 32 + 4 + 4 + 32 + 4 + 4 + 1 + 1 + 4 + 4 + 4 + 4 value := make([]byte, n) copy(value, v.Genesis[:32]) binary.BigEndian.PutUint32(value[32:], v.Height) binary.BigEndian.PutUint32(value[32+4:], v.TxCount) copy(value[32+4+4:], v.Tip[:32]) binary.BigEndian.PutUint32(value[32+4+4+32:], v.UtxoFlushCount) binary.BigEndian.PutUint32(value[32+4+4+32+4:], v.WallTime) var bitSetVar uint8 if v.FirstSync { bitSetVar = 1 } value[32+4+4+32+4+4] = bitSetVar value[32+4+4+32+4+4+1] = v.DBVersion binary.BigEndian.PutUint32(value[32+4+4+32+4+4+1+1:], uint32(v.HistFlushCount)) binary.BigEndian.PutUint32(value[32+4+4+32+4+4+1+1+4:], uint32(v.CompFlushCount)) binary.BigEndian.PutUint32(value[32+4+4+32+4+4+1+1+4+4:], uint32(v.CompCursor)) binary.BigEndian.PutUint32(value[32+4+4+32+4+4+1+1+4+4+4:], v.EsSyncHeight) return value } func (kv *DBStateKey) NumFields() int { return 0 } func (k *DBStateKey) PartialPack(fields int) []byte { prefixLen := 1 var n = prefixLen key := make([]byte, n) copy(key, k.Prefix) return key } func DBStateKeyUnpack(key []byte) *DBStateKey { prefixLen := 1 return &DBStateKey{ Prefix: key[:prefixLen], } } func DBStateValueUnpack(value []byte) *DBStateValue { genesis := (*chainhash.Hash)(value[:32]) tip := (*chainhash.Hash)(value[32+4+4 : 32+4+4+32]) x := &DBStateValue{ Genesis: genesis, Height: binary.BigEndian.Uint32(value[32:]), TxCount: binary.BigEndian.Uint32(value[32+4:]), Tip: tip, UtxoFlushCount: binary.BigEndian.Uint32(value[32+4+4+32:]), WallTime: binary.BigEndian.Uint32(value[32+4+4+32+4:]), FirstSync: value[32+4+4+32+4+4] == 1, DBVersion: value[32+4+4+32+4+4+1], HistFlushCount: int32(binary.BigEndian.Uint32(value[32+4+4+32+4+4+1+1:])), CompFlushCount: int32(binary.BigEndian.Uint32(value[32+4+4+32+4+4+1+1+4:])), CompCursor: int32(binary.BigEndian.Uint32(value[32+4+4+32+4+4+1+1+4+4:])), EsSyncHeight: binary.BigEndian.Uint32(value[32+4+4+32+4+4+1+1+4+4+4:]), } return x } type UndoKey struct { Prefix []byte `struct:"[1]byte" json:"prefix"` Height uint64 `json:"height"` } type UndoValue struct { Data []byte `struct-while:"!_eof" json:"data"` } func (k *UndoKey) PackKey() []byte { prefixLen := 1 // b'>L' n := prefixLen + 8 key := make([]byte, n) copy(key, k.Prefix) binary.BigEndian.PutUint64(key[prefixLen:], k.Height) return key } func (v *UndoValue) PackValue() []byte { len := len(v.Data) value := make([]byte, len) copy(value, v.Data) return value } func (kv *UndoKey) NumFields() int { return 1 } func (k *UndoKey) PartialPack(fields int) []byte { // Limit fields between 0 and number of fields, we always at least need // the prefix, and we never need to iterate past the number of fields. if fields > 1 { fields = 1 } if fields < 0 { fields = 0 } // b'>4sLH' prefixLen := 1 var n = prefixLen for i := 0; i <= fields; i++ { switch i { case 1: n += 8 } } key := make([]byte, n) for i := 0; i <= fields; i++ { switch i { case 0: copy(key, k.Prefix) case 1: binary.BigEndian.PutUint64(key[prefixLen:], k.Height) } } return key } func UndoKeyUnpack(key []byte) *UndoKey { prefixLen := 1 return &UndoKey{ Prefix: key[:prefixLen], Height: binary.BigEndian.Uint64(key[prefixLen:]), } } func UndoValueUnpack(value []byte) *UndoValue { return &UndoValue{ Data: value, } } type UTXOKey struct { Prefix []byte `struct:"[1]byte" json:"prefix"` HashX []byte `struct:"[11]byte" json:"hashx"` TxNum uint32 `json:"tx_num"` Nout uint16 `json:"nout"` } type UTXOValue struct { Amount uint64 `json:"amount"` } type HashXUTXOKey struct { Prefix []byte `struct:"[1]byte" json:"prefix"` ShortTXHash []byte `struct:"[4]byte" json:"short_tx_hash"` TxNum uint32 `json:"tx_num"` Nout uint16 `json:"nout"` } type HashXUTXOValue struct { HashX []byte `struct:"[11]byte" json:"hashx"` } // // HashXUTXOKey / HashXUTXOValue // func (k *HashXUTXOKey) String() string { return fmt.Sprintf( "%s(short_tx_hash=%s, tx_num=%d, nout=%d)", reflect.TypeOf(k), hex.EncodeToString(k.ShortTXHash), k.TxNum, k.Nout, ) } func (v *HashXUTXOValue) String() string { return fmt.Sprintf( "%s(hashX=%s)", reflect.TypeOf(v), hex.EncodeToString(v.HashX), ) } func (k *HashXUTXOKey) PackKey() []byte { prefixLen := 1 // b'>4sLH' n := prefixLen + 4 + 4 + 2 key := make([]byte, n) copy(key, k.Prefix) copy(key[prefixLen:], k.ShortTXHash) binary.BigEndian.PutUint32(key[prefixLen+4:], k.TxNum) binary.BigEndian.PutUint16(key[prefixLen+8:], k.Nout) return key } func (v *HashXUTXOValue) PackValue() []byte { value := make([]byte, 11) copy(value, v.HashX) return value } func (kv *HashXUTXOKey) NumFields() int { return 3 } // HashXUTXOKeyPackPartial packs a variable number of fields into a byte // array func (k *HashXUTXOKey) PartialPack(fields int) []byte { // Limit fields between 0 and number of fields, we always at least need // the prefix, and we never need to iterate past the number of fields. if fields > 3 { fields = 3 } if fields < 0 { fields = 0 } // b'>4sLH' prefixLen := 1 var n = prefixLen for i := 0; i <= fields; i++ { switch i { case 1: n += 4 case 2: n += 4 case 3: n += 2 } } key := make([]byte, n) for i := 0; i <= fields; i++ { switch i { case 0: copy(key, k.Prefix) case 1: copy(key[prefixLen:], k.ShortTXHash) case 2: binary.BigEndian.PutUint32(key[prefixLen+4:], k.TxNum) case 3: binary.BigEndian.PutUint16(key[prefixLen+8:], k.Nout) } } return key } func HashXUTXOKeyUnpack(key []byte) *HashXUTXOKey { prefixLen := 1 return &HashXUTXOKey{ Prefix: key[:prefixLen], ShortTXHash: key[prefixLen : prefixLen+4], TxNum: binary.BigEndian.Uint32(key[prefixLen+4:]), Nout: binary.BigEndian.Uint16(key[prefixLen+8:]), } } func HashXUTXOValueUnpack(value []byte) *HashXUTXOValue { return &HashXUTXOValue{ HashX: value[:11], } } type HashXHistoryKey struct { Prefix []byte `struct:"[1]byte" json:"prefix"` HashX []byte `struct:"[11]byte" json:"hashx"` Height uint32 `json:"height"` } type HashXHistoryValue struct { TxNums []uint32 `struct:"lsb" struct-while:"!_eof" json:"tx_nums"` } func (k *HashXHistoryKey) String() string { return fmt.Sprintf( "%s(hashx=%s, height=%d)", reflect.TypeOf(k), hex.EncodeToString(k.HashX), k.Height, ) } func (k *HashXHistoryKey) PackKey() []byte { prefixLen := 1 // b'>11sL' n := prefixLen + 11 + 4 key := make([]byte, n) copy(key, k.Prefix) copy(key[prefixLen:], k.HashX) binary.BigEndian.PutUint32(key[prefixLen+11:], k.Height) return key } func (v *HashXHistoryValue) PackValue() []byte { n := len(v.TxNums) value := make([]byte, n*4) for i, x := range v.TxNums { binary.LittleEndian.PutUint32(value[i*4:], x) } return value } func (kv *HashXHistoryKey) NumFields() int { return 2 } // HashXHistoryKeyPackPartial packs a variable number of fields into a byte // array func (k *HashXHistoryKey) PartialPack(fields int) []byte { // Limit fields between 0 and number of fields, we always at least need // the prefix, and we never need to iterate past the number of fields. if fields > 2 { fields = 2 } if fields < 0 { fields = 0 } prefixLen := 1 var n = prefixLen for i := 0; i <= fields; i++ { switch i { case 1: n += 11 case 2: n += 4 } } key := make([]byte, n) for i := 0; i <= fields; i++ { switch i { case 0: copy(key, k.Prefix) case 1: copy(key[prefixLen:], k.HashX[:11]) case 2: binary.BigEndian.PutUint32(key[prefixLen+11:], k.Height) } } return key } func HashXHistoryKeyUnpack(key []byte) *HashXHistoryKey { prefixLen := 1 return &HashXHistoryKey{ Prefix: key[:prefixLen], HashX: key[prefixLen : prefixLen+11], Height: binary.BigEndian.Uint32(key[prefixLen+11:]), } } func HashXHistoryValueUnpack(value []byte) *HashXHistoryValue { n := len(value) / 4 txnums := make([]uint32, n) for i := 0; i < n; i++ { txnums[i] = binary.LittleEndian.Uint32(value[i*4:]) } return &HashXHistoryValue{ TxNums: txnums, } } type BlockHashKey struct { Prefix []byte `struct:"[1]byte" json:"prefix"` Height uint32 `json:"height"` } type BlockHashValue struct { BlockHash *chainhash.Hash `json:"block_hash"` } func NewBlockHashKey(height uint32) *BlockHashKey { return &BlockHashKey{ Prefix: []byte{BlockHash}, Height: height, } } func (k *BlockHashKey) PackKey() []byte { prefixLen := 1 // b'>L' n := prefixLen + 4 key := make([]byte, n) copy(key, k.Prefix) binary.BigEndian.PutUint32(key[prefixLen:], k.Height) return key } func (v *BlockHashValue) PackValue() []byte { value := make([]byte, 32) copy(value, v.BlockHash[:32]) return value } func (kv *BlockHashKey) NumFields() int { return 1 } func (k *BlockHashKey) PartialPack(fields int) []byte { // Limit fields between 0 and number of fields, we always at least need // the prefix, and we never need to iterate past the number of fields. if fields > 1 { fields = 1 } if fields < 0 { fields = 0 } // b'>4sLH' prefixLen := 1 var n = prefixLen for i := 0; i <= fields; i++ { switch i { case 1: n += 4 case 2: n += 4 case 3: n += 2 } } key := make([]byte, n) for i := 0; i <= fields; i++ { switch i { case 0: copy(key, k.Prefix) case 1: binary.BigEndian.PutUint32(key[prefixLen:], k.Height) } } return key } func BlockHashKeyUnpack(key []byte) *BlockHashKey { prefixLen := 1 return &BlockHashKey{ Prefix: key[:prefixLen], Height: binary.BigEndian.Uint32(key[prefixLen:]), } } func BlockHashValueUnpack(value []byte) *BlockHashValue { hash := (*chainhash.Hash)(value) return &BlockHashValue{ BlockHash: hash, } } type BlockTxsKey struct { Prefix []byte `struct:"[1]byte" json:"prefix"` Height uint32 `json:"height"` } type BlockTxsValue struct { TxHashes []*chainhash.Hash `struct-while:"!_eof" json:"tx_hashes"` } func (k *BlockTxsKey) NewBlockTxsKey(height uint32) *BlockTxsKey { return &BlockTxsKey{ Prefix: []byte{BlockTXs}, Height: height, } } func (k *BlockTxsKey) PackKey() []byte { prefixLen := 1 // b'>L' n := prefixLen + 4 key := make([]byte, n) copy(key, k.Prefix) binary.BigEndian.PutUint32(key[prefixLen:], k.Height) return key } func (v *BlockTxsValue) PackValue() []byte { numHashes := len(v.TxHashes) n := numHashes * 32 value := make([]byte, n) for i, tx := range v.TxHashes { if len(tx) != 32 { log.Println("Warning, txhash not 32 bytes", tx) return nil } copy(value[i*32:], tx[:]) } return value } func (kv *BlockTxsKey) NumFields() int { return 1 } func (k *BlockTxsKey) PartialPack(fields int) []byte { // Limit fields between 0 and number of fields, we always at least need // the prefix, and we never need to iterate past the number of fields. if fields > 1 { fields = 1 } if fields < 0 { fields = 0 } prefixLen := 1 var n = prefixLen for i := 0; i <= fields; i++ { switch i { case 1: n += 4 } } key := make([]byte, n) for i := 0; i <= fields; i++ { switch i { case 0: copy(key, k.Prefix) case 1: binary.BigEndian.PutUint32(key[prefixLen:], k.Height) } } return key } func BlockTxsKeyUnpack(key []byte) *BlockTxsKey { prefixLen := 1 return &BlockTxsKey{ Prefix: key[:prefixLen], Height: binary.BigEndian.Uint32(key[prefixLen:]), } } func BlockTxsValueUnpack(value []byte) *BlockTxsValue { numHashes := len(value) / 32 txs := make([]*chainhash.Hash, numHashes) for i := 0; i < numHashes; i++ { txs[i] = (*chainhash.Hash)(value[i*32 : (i+1)*32]) } return &BlockTxsValue{ TxHashes: txs, } } type TxCountKey struct { Prefix []byte `struct:"[1]byte" json:"prefix"` Height uint32 `json:"height"` } type TxCountValue struct { TxCount uint32 `json:"tx_count"` } func NewTxCountKey(height uint32) *TxCountKey { return &TxCountKey{ Prefix: []byte{TxCount}, Height: height, } } func (k *TxCountKey) PackKey() []byte { prefixLen := 1 // b'>L' n := prefixLen + 4 key := make([]byte, n) copy(key, k.Prefix) binary.BigEndian.PutUint32(key[prefixLen:], k.Height) return key } func (v *TxCountValue) PackValue() []byte { value := make([]byte, 4) binary.BigEndian.PutUint32(value, v.TxCount) return value } func (kv *TxCountKey) NumFields() int { return 1 } func (k *TxCountKey) PartialPack(fields int) []byte { // Limit fields between 0 and number of fields, we always at least need // the prefix, and we never need to iterate past the number of fields. if fields > 1 { fields = 1 } if fields < 0 { fields = 0 } prefixLen := 1 var n = prefixLen for i := 0; i <= fields; i++ { switch i { case 1: n += 4 } } key := make([]byte, n) for i := 0; i <= fields; i++ { switch i { case 0: copy(key, k.Prefix) case 1: binary.BigEndian.PutUint32(key[prefixLen:], k.Height) } } return key } func TxCountKeyUnpack(key []byte) *TxCountKey { prefixLen := 1 return &TxCountKey{ Prefix: key[:prefixLen], Height: binary.BigEndian.Uint32(key[prefixLen:]), } } func TxCountValueUnpack(value []byte) *TxCountValue { return &TxCountValue{ TxCount: binary.BigEndian.Uint32(value), } } type TxHashKey struct { Prefix []byte `struct:"[1]byte" json:"prefix"` TxNum uint32 `json:"tx_num"` } type TxHashValue struct { TxHash *chainhash.Hash `json:"tx_hash"` } func NewTxHashKey(txNum uint32) *TxHashKey { return &TxHashKey{ Prefix: []byte{TxHash}, TxNum: txNum, } } func (k *TxHashKey) PackKey() []byte { prefixLen := 1 // b'>L' n := prefixLen + 4 key := make([]byte, n) copy(key, k.Prefix) binary.BigEndian.PutUint32(key[prefixLen:], k.TxNum) return key } func (v *TxHashValue) PackValue() []byte { n := len(v.TxHash) value := make([]byte, n) copy(value, v.TxHash[:n]) return value } func (kv *TxHashKey) NumFields() int { return 1 } func (k *TxHashKey) PartialPack(fields int) []byte { // Limit fields between 0 and number of fields, we always at least need // the prefix, and we never need to iterate past the number of fields. if fields > 1 { fields = 1 } if fields < 0 { fields = 0 } prefixLen := 1 var n = prefixLen for i := 0; i <= fields; i++ { switch i { case 1: n += 4 } } key := make([]byte, n) for i := 0; i <= fields; i++ { switch i { case 0: copy(key, k.Prefix) case 1: binary.BigEndian.PutUint32(key[prefixLen:], k.TxNum) } } return key } func TxHashKeyUnpack(key []byte) *TxHashKey { prefixLen := 1 return &TxHashKey{ Prefix: key[:prefixLen], TxNum: binary.BigEndian.Uint32(key[prefixLen:]), } } func TxHashValueUnpack(value []byte) *TxHashValue { return &TxHashValue{ TxHash: (*chainhash.Hash)(value), } } type TxNumKey struct { Prefix []byte `struct:"[1]byte" json:"prefix"` TxHash *chainhash.Hash `json:"tx_hash"` } type TxNumValue struct { TxNum uint32 `json:"tx_num"` } func (k *TxNumKey) PackKey() []byte { prefixLen := 1 // b'>L' n := prefixLen + 32 key := make([]byte, n) copy(key, k.Prefix) copy(key[prefixLen:], k.TxHash[:32]) return key } func (v *TxNumValue) PackValue() []byte { value := make([]byte, 4) binary.BigEndian.PutUint32(value, v.TxNum) return value } func (kv *TxNumKey) NumFields() int { return 1 } func (k *TxNumKey) PartialPack(fields int) []byte { // Limit fields between 0 and number of fields, we always at least need // the prefix, and we never need to iterate past the number of fields. if fields > 1 { fields = 1 } if fields < 0 { fields = 0 } prefixLen := 1 var n = prefixLen for i := 0; i <= fields; i++ { switch i { case 1: n += 32 } } key := make([]byte, n) for i := 0; i <= fields; i++ { switch i { case 0: copy(key, k.Prefix) case 1: copy(key[prefixLen:], k.TxHash[:32]) } } return key } func TxNumKeyUnpack(key []byte) *TxNumKey { prefixLen := 1 return &TxNumKey{ Prefix: key[:prefixLen], TxHash: (*chainhash.Hash)(key[prefixLen : prefixLen+32]), } } func TxNumValueUnpack(value []byte) *TxNumValue { return &TxNumValue{ TxNum: binary.BigEndian.Uint32(value), } } type BlockHeaderKey struct { Prefix []byte `struct:"[1]byte" json:"prefix"` Height uint32 `json:"height"` } type BlockHeaderValue struct { Header []byte `struct:"[112]byte" json:"header"` } func (k *BlockHeaderValue) Equals(v *BlockHeaderValue) bool { return bytes.Equal(k.Header, v.Header) } func NewHeaderKey(height uint32) *BlockHeaderKey { return &BlockHeaderKey{ Prefix: []byte{Header}, Height: height, } } func (k *BlockHeaderKey) PackKey() []byte { prefixLen := 1 // b'>L' n := prefixLen + 4 key := make([]byte, n) copy(key, k.Prefix) binary.BigEndian.PutUint32(key[prefixLen:], k.Height) return key } func (v *BlockHeaderValue) PackValue() []byte { value := make([]byte, 112) copy(value, v.Header) return value } func (kv *BlockHeaderKey) NumFields() int { return 1 } func (k *BlockHeaderKey) PartialPack(fields int) []byte { // Limit fields between 0 and number of fields, we always at least need // the prefix, and we never need to iterate past the number of fields. if fields > 1 { fields = 1 } if fields < 0 { fields = 0 } // b'>4sLH' prefixLen := 1 var n = prefixLen for i := 0; i <= fields; i++ { switch i { case 1: n += 4 } } key := make([]byte, n) for i := 0; i <= fields; i++ { switch i { case 0: copy(key, k.Prefix) case 1: binary.BigEndian.PutUint32(key[prefixLen:], k.Height) } } return key } func BlockHeaderKeyUnpack(key []byte) *BlockHeaderKey { prefixLen := 1 return &BlockHeaderKey{ Prefix: key[:prefixLen], Height: binary.BigEndian.Uint32(key[prefixLen:]), } } func BlockHeaderValueUnpack(value []byte) *BlockHeaderValue { return &BlockHeaderValue{ Header: value[:112], } } type ClaimToTXOKey struct { Prefix []byte `struct:"[1]byte" json:"prefix"` ClaimHash []byte `struct:"[20]byte" json:"claim_hash"` } type ClaimToTXOValue struct { TxNum uint32 `json:"tx_num"` Position uint16 `json:"position"` RootTxNum uint32 `json:"root_tx_num"` RootPosition uint16 `json:"root_position"` Amount uint64 `json:"amount"` ChannelSignatureIsValid bool `json:"channel_signature_is_valid"` LengthEncodedName } func NewClaimToTXOKey(claimHash []byte) *ClaimToTXOKey { return &ClaimToTXOKey{ Prefix: []byte{ClaimToTXO}, ClaimHash: claimHash, } } func (v *ClaimToTXOValue) NormalizedName() string { //TODO implement? Might not need to do anything. return internal.NormalizeName(v.Name) } func (k *ClaimToTXOKey) PackKey() []byte { prefixLen := 1 // b'>20s' n := prefixLen + 20 key := make([]byte, n) copy(key, k.Prefix) copy(key[prefixLen:], k.ClaimHash[:20]) return key } func (v *ClaimToTXOValue) PackValue() []byte { nameLen := len(v.Name) n := 4 + 2 + 4 + 2 + 8 + 1 + 2 + nameLen value := make([]byte, n) binary.BigEndian.PutUint32(value, v.TxNum) binary.BigEndian.PutUint16(value[4:], v.Position) binary.BigEndian.PutUint32(value[6:], v.RootTxNum) binary.BigEndian.PutUint16(value[10:], v.RootPosition) binary.BigEndian.PutUint64(value[12:], v.Amount) var bitSetVar uint8 if v.ChannelSignatureIsValid { bitSetVar = 1 } value[20] = bitSetVar binary.BigEndian.PutUint16(value[21:], uint16(nameLen)) copy(value[23:], []byte(v.Name[:nameLen])) return value } func (kv *ClaimToTXOKey) NumFields() int { return 1 } func (k *ClaimToTXOKey) PartialPack(fields int) []byte { // Limit fields between 0 and number of fields, we always at least need // the prefix, and we never need to iterate past the number of fields. if fields > 1 { fields = 1 } if fields < 0 { fields = 0 } // b'>4sLH' prefixLen := 1 var n = prefixLen for i := 0; i <= fields; i++ { switch i { case 1: n += 20 } } key := make([]byte, n) for i := 0; i <= fields; i++ { switch i { case 0: copy(key, k.Prefix) case 1: copy(key[prefixLen:], k.ClaimHash[:20]) } } return key } func ClaimToTXOKeyUnpack(key []byte) *ClaimToTXOKey { prefixLen := 1 return &ClaimToTXOKey{ Prefix: key[:prefixLen], ClaimHash: key[prefixLen : prefixLen+20], } } func ClaimToTXOValueUnpack(value []byte) *ClaimToTXOValue { nameLen := binary.BigEndian.Uint16(value[21:]) return &ClaimToTXOValue{ TxNum: binary.BigEndian.Uint32(value), Position: binary.BigEndian.Uint16(value[4:]), RootTxNum: binary.BigEndian.Uint32(value[6:]), RootPosition: binary.BigEndian.Uint16(value[10:]), Amount: binary.BigEndian.Uint64(value[12:]), ChannelSignatureIsValid: value[20] == 1, LengthEncodedName: NewLengthEncodedName(string(value[23 : 23+nameLen])), } } type TXOToClaimKey struct { Prefix []byte `struct:"[1]byte" json:"prefix"` TxNum uint32 `json:"tx_num"` Position uint16 `json:"position"` } type TXOToClaimValue struct { ClaimHash []byte `struct:"[20]byte" json:"claim_hash"` LengthEncodedName } func NewTXOToClaimKey(txNum uint32, position uint16) *TXOToClaimKey { return &TXOToClaimKey{ Prefix: []byte{TXOToClaim}, TxNum: txNum, Position: position, } } func (k *TXOToClaimKey) PackKey() []byte { prefixLen := 1 // b'>LH' n := prefixLen + 4 + 2 key := make([]byte, n) copy(key, k.Prefix) binary.BigEndian.PutUint32(key[prefixLen:], k.TxNum) binary.BigEndian.PutUint16(key[prefixLen+4:], k.Position) return key } func (v *TXOToClaimValue) PackValue() []byte { nameLen := len(v.Name) n := 20 + 2 + nameLen value := make([]byte, n) copy(value, v.ClaimHash[:20]) binary.BigEndian.PutUint16(value[20:], uint16(nameLen)) copy(value[22:], []byte(v.Name)) return value } func (kv *TXOToClaimKey) NumFields() int { return 2 } func (k *TXOToClaimKey) PartialPack(fields int) []byte { // Limit fields between 0 and number of fields, we always at least need // the prefix, and we never need to iterate past the number of fields. if fields > 2 { fields = 2 } if fields < 0 { fields = 0 } prefixLen := 1 var n = prefixLen for i := 0; i <= fields; i++ { switch i { case 1: n += 4 case 2: n += 2 } } key := make([]byte, n) for i := 0; i <= fields; i++ { switch i { case 0: copy(key, k.Prefix) case 1: binary.BigEndian.PutUint32(key[prefixLen:], k.TxNum) case 2: binary.BigEndian.PutUint16(key[prefixLen+4:], k.Position) } } return key } func TXOToClaimKeyUnpack(key []byte) *TXOToClaimKey { prefixLen := 1 return &TXOToClaimKey{ Prefix: key[:prefixLen], TxNum: binary.BigEndian.Uint32(key[prefixLen:]), Position: binary.BigEndian.Uint16(key[prefixLen+4:]), } } func TXOToClaimValueUnpack(value []byte) *TXOToClaimValue { nameLen := binary.BigEndian.Uint16(value[20:]) return &TXOToClaimValue{ ClaimHash: value[:20], LengthEncodedName: NewLengthEncodedName(string(value[22 : 22+nameLen])), } } type ClaimShortIDKey struct { Prefix []byte `struct:"[1]byte" json:"prefix"` LengthEncodedNormalizedName // fields NormalizedNameLen, NormalizedName LengthEncodedPartialClaimId // fields PartialClaimIdLen, PartialClaimId RootTxNum uint32 `json:"root_tx_num"` RootPosition uint16 `json:"root_position"` } type ClaimShortIDValue struct { TxNum uint32 `json:"tx_num"` Position uint16 `json:"position"` } func NewClaimShortIDKey(normalizedName, partialClaimId string) *ClaimShortIDKey { return &ClaimShortIDKey{ Prefix: []byte{ClaimShortIdPrefix}, LengthEncodedNormalizedName: NewLengthEncodedNormalizedName(normalizedName), LengthEncodedPartialClaimId: NewLengthEncodedPartialClaimId(partialClaimId), } } func (k *ClaimShortIDKey) PackKey() []byte { prefixLen := 1 nameLen := len(k.NormalizedName) partialClaimLen := len(k.PartialClaimId) log.Printf("nameLen: %d, partialClaimLen: %d\n", nameLen, partialClaimLen) n := prefixLen + 2 + nameLen + 1 + partialClaimLen + 4 + 2 key := make([]byte, n) copy(key, k.Prefix) binary.BigEndian.PutUint16(key[prefixLen:], uint16(nameLen)) copy(key[prefixLen+2:], []byte(k.NormalizedName[:nameLen])) key[prefixLen+2+nameLen] = uint8(partialClaimLen) copy(key[prefixLen+2+nameLen+1:], []byte(k.PartialClaimId[:partialClaimLen])) binary.BigEndian.PutUint32(key[prefixLen+2+nameLen+1+partialClaimLen:], k.RootTxNum) binary.BigEndian.PutUint16(key[prefixLen+2+nameLen+1+partialClaimLen+4:], k.RootPosition) return key } func (v *ClaimShortIDValue) PackValue() []byte { value := make([]byte, 6) binary.BigEndian.PutUint32(value, v.TxNum) binary.BigEndian.PutUint16(value[4:], v.Position) return value } func (kv *ClaimShortIDKey) NumFields() int { return 4 } func (k *ClaimShortIDKey) PartialPack(fields int) []byte { // Limit fields between 0 and number of fields, we always at least need // the prefix, and we never need to iterate past the number of fields. if fields > 4 { fields = 4 } if fields < 0 { fields = 0 } // b'>4sLH' prefixLen := 1 nameLen := len(k.NormalizedName) partialClaimLen := len(k.PartialClaimId) var n = prefixLen for i := 0; i <= fields; i++ { switch i { case 1: n += 2 + nameLen case 2: n += 1 + partialClaimLen case 3: n += 4 case 4: n += 2 } } key := make([]byte, n) for i := 0; i <= fields; i++ { switch i { case 0: copy(key, k.Prefix) case 1: binary.BigEndian.PutUint16(key[prefixLen:], uint16(nameLen)) copy(key[prefixLen+2:], []byte(k.NormalizedName)) case 2: key[prefixLen+2+nameLen] = uint8(partialClaimLen) copy(key[prefixLen+2+nameLen+1:], []byte(k.PartialClaimId)) case 3: binary.BigEndian.PutUint32(key[prefixLen+2+nameLen+1+partialClaimLen:], k.RootTxNum) case 4: binary.BigEndian.PutUint16(key[prefixLen+2+nameLen+1+partialClaimLen+4:], k.RootPosition) } } return key } func ClaimShortIDKeyUnpack(key []byte) *ClaimShortIDKey { prefixLen := 1 nameLen := int(binary.BigEndian.Uint16(key[prefixLen:])) partialClaimLen := int(uint8(key[prefixLen+2+nameLen])) return &ClaimShortIDKey{ Prefix: key[:prefixLen], LengthEncodedNormalizedName: NewLengthEncodedNormalizedName(string(key[prefixLen+2 : prefixLen+2+nameLen])), LengthEncodedPartialClaimId: NewLengthEncodedPartialClaimId(string(key[prefixLen+2+nameLen+1 : prefixLen+2+nameLen+1+partialClaimLen])), RootTxNum: binary.BigEndian.Uint32(key[prefixLen+2+nameLen+1+partialClaimLen:]), RootPosition: binary.BigEndian.Uint16(key[prefixLen+2+nameLen+1+partialClaimLen+4:]), } } func ClaimShortIDValueUnpack(value []byte) *ClaimShortIDValue { return &ClaimShortIDValue{ TxNum: binary.BigEndian.Uint32(value), Position: binary.BigEndian.Uint16(value[4:]), } } type ClaimToChannelKey struct { Prefix []byte `struct:"[1]byte" json:"prefix"` ClaimHash []byte `struct:"[20]byte" json:"claim_hash"` TxNum uint32 `json:"tx_num"` Position uint16 `json:"position"` } type ClaimToChannelValue struct { SigningHash []byte `struct:"[20]byte" json:"signing_hash"` } func NewClaimToChannelKey(claimHash []byte, txNum uint32, position uint16) *ClaimToChannelKey { return &ClaimToChannelKey{ Prefix: []byte{ClaimToChannel}, ClaimHash: claimHash, TxNum: txNum, Position: position, } } func (k *ClaimToChannelKey) PackKey() []byte { prefixLen := 1 // b'>20sLH' n := prefixLen + 20 + 4 + 2 key := make([]byte, n) copy(key, k.Prefix) copy(key[prefixLen:], k.ClaimHash[:20]) binary.BigEndian.PutUint32(key[prefixLen+20:], k.TxNum) binary.BigEndian.PutUint16(key[prefixLen+24:], k.Position) return key } func (v *ClaimToChannelValue) PackValue() []byte { value := make([]byte, 20) copy(value, v.SigningHash[:20]) return value } func (kv *ClaimToChannelKey) NumFields() int { return 3 } func (k *ClaimToChannelKey) PartialPack(fields int) []byte { // Limit fields between 0 and number of fields, we always at least need // the prefix, and we never need to iterate past the number of fields. if fields > 3 { fields = 3 } if fields < 0 { fields = 0 } // b'>4sLH' prefixLen := 1 var n = prefixLen for i := 0; i <= fields; i++ { switch i { case 1: n += 20 case 2: n += 4 case 3: n += 2 } } key := make([]byte, n) for i := 0; i <= fields; i++ { switch i { case 0: copy(key, k.Prefix) case 1: copy(key[prefixLen:], k.ClaimHash[:20]) case 2: binary.BigEndian.PutUint32(key[prefixLen+20:], k.TxNum) case 3: binary.BigEndian.PutUint16(key[prefixLen+24:], k.Position) } } return key } func ClaimToChannelKeyUnpack(key []byte) *ClaimToChannelKey { prefixLen := 1 return &ClaimToChannelKey{ Prefix: key[:prefixLen], ClaimHash: key[prefixLen : prefixLen+20], TxNum: binary.BigEndian.Uint32(key[prefixLen+20:]), Position: binary.BigEndian.Uint16(key[prefixLen+24:]), } } func ClaimToChannelValueUnpack(value []byte) *ClaimToChannelValue { return &ClaimToChannelValue{ SigningHash: value[:20], } } type ChannelToClaimKey struct { Prefix []byte `struct:"[1]byte" json:"prefix"` SigningHash []byte `struct:"[20]byte" json:"signing_hash"` LengthEncodedName // fields NameLen, Name TxNum uint32 `json:"tx_num"` Position uint16 `json:"position"` } type ChannelToClaimValue struct { ClaimHash []byte `struct:"[20]byte" json:"claim_hash"` } func NewChannelToClaimKey(channelHash []byte, normalizedName string) *ChannelToClaimKey { return &ChannelToClaimKey{ Prefix: []byte{ChannelToClaim}, SigningHash: channelHash, LengthEncodedName: NewLengthEncodedName(normalizedName), } } func NewChannelToClaimKeyWHash(channelHash []byte) *ChannelToClaimKey { return &ChannelToClaimKey{ Prefix: []byte{ChannelToClaim}, SigningHash: channelHash, } } func (k *ChannelToClaimKey) PackKey() []byte { prefixLen := 1 nameLen := len(k.Name) n := prefixLen + 20 + 2 + nameLen + 4 + 2 key := make([]byte, n) copy(key, k.Prefix) copy(key[prefixLen:], k.SigningHash[:20]) binary.BigEndian.PutUint16(key[prefixLen+20:], uint16(nameLen)) copy(key[prefixLen+22:], []byte(k.Name[:nameLen])) binary.BigEndian.PutUint32(key[prefixLen+22+nameLen:], k.TxNum) binary.BigEndian.PutUint16(key[prefixLen+22+nameLen+4:], k.Position) return key } func (v *ChannelToClaimValue) PackValue() []byte { value := make([]byte, 20) copy(value, v.ClaimHash[:20]) return value } func (kv *ChannelToClaimKey) NumFields() int { return 4 } func (k *ChannelToClaimKey) PartialPack(fields int) []byte { // Limit fields between 0 and number of fields, we always at least need // the prefix, and we never need to iterate past the number of fields. if fields > 4 { fields = 4 } if fields < 0 { fields = 0 } nameLen := len(k.Name) prefixLen := 1 var n = prefixLen for i := 0; i <= fields; i++ { switch i { case 1: n += 20 case 2: n += 2 + nameLen case 3: n += 4 case 4: n += 2 } } key := make([]byte, n) for i := 0; i <= fields; i++ { switch i { case 0: copy(key, k.Prefix) case 1: copy(key[prefixLen:], k.SigningHash[:20]) case 2: binary.BigEndian.PutUint16(key[prefixLen+20:], uint16(nameLen)) copy(key[prefixLen+22:], []byte(k.Name)) case 3: binary.BigEndian.PutUint32(key[prefixLen+22+nameLen:], k.TxNum) case 4: binary.BigEndian.PutUint16(key[prefixLen+22+nameLen+4:], k.Position) } } return key } func ChannelToClaimKeyUnpack(key []byte) *ChannelToClaimKey { prefixLen := 1 nameLen := int(binary.BigEndian.Uint16(key[prefixLen+20:])) return &ChannelToClaimKey{ Prefix: key[:prefixLen], SigningHash: key[prefixLen : prefixLen+20], LengthEncodedName: NewLengthEncodedName(string(key[prefixLen+22 : prefixLen+22+nameLen])), TxNum: binary.BigEndian.Uint32(key[prefixLen+22+nameLen:]), Position: binary.BigEndian.Uint16(key[prefixLen+22+nameLen+4:]), } } func ChannelToClaimValueUnpack(value []byte) *ChannelToClaimValue { return &ChannelToClaimValue{ ClaimHash: value[:20], } } type ChannelCountKey struct { Prefix []byte `struct:"[1]byte" json:"prefix"` ChannelHash []byte `struct:"[20]byte" json:"channel_hash"` } type ChannelCountValue struct { Count uint32 `json:"count"` } func NewChannelCountKey(channelHash []byte) *ChannelCountKey { return &ChannelCountKey{ Prefix: []byte{ChannelCount}, ChannelHash: channelHash, } } func (k *ChannelCountKey) PackKey() []byte { prefixLen := 1 // b'>20sLH' n := prefixLen + 20 key := make([]byte, n) copy(key, k.Prefix) copy(key[prefixLen:], k.ChannelHash[:20]) return key } func (v *ChannelCountValue) PackValue() []byte { value := make([]byte, 4) binary.BigEndian.PutUint32(value, v.Count) return value } func (kv *ChannelCountKey) NumFields() int { return 1 } func (k *ChannelCountKey) PartialPack(fields int) []byte { // Limit fields between 0 and number of fields, we always at least need // the prefix, and we never need to iterate past the number of fields. if fields > 1 { fields = 1 } if fields < 0 { fields = 0 } prefixLen := 1 var n = prefixLen for i := 0; i <= fields; i++ { switch i { case 1: n += 20 } } key := make([]byte, n) for i := 0; i <= fields; i++ { switch i { case 0: copy(key, k.Prefix) case 1: copy(key[prefixLen:], k.ChannelHash) } } return key } func ChannelCountKeyUnpack(key []byte) *ChannelCountKey { prefixLen := 1 return &ChannelCountKey{ Prefix: key[:prefixLen], ChannelHash: key[prefixLen : prefixLen+20], } } func ChannelCountValueUnpack(value []byte) *ChannelCountValue { return &ChannelCountValue{ Count: binary.BigEndian.Uint32(value), } } type SupportAmountKey struct { Prefix []byte `struct:"[1]byte" json:"prefix"` ClaimHash []byte `struct:"[20]byte" json:"claim_hash"` } type SupportAmountValue struct { Amount uint64 `json:"amount"` } func NewSupportAmountKey(claimHash []byte) *SupportAmountKey { return &SupportAmountKey{ Prefix: []byte{SupportAmount}, ClaimHash: claimHash, } } func (k *SupportAmountKey) PackKey() []byte { prefixLen := 1 // b'>20sLH' n := prefixLen + 20 key := make([]byte, n) copy(key, k.Prefix) copy(key[prefixLen:], k.ClaimHash[:20]) return key } func (v *SupportAmountValue) PackValue() []byte { value := make([]byte, 8) binary.BigEndian.PutUint64(value, v.Amount) return value } func (kv *SupportAmountKey) NumFields() int { return 1 } func (k *SupportAmountKey) PartialPack(fields int) []byte { // Limit fields between 0 and number of fields, we always at least need // the prefix, and we never need to iterate past the number of fields. if fields > 1 { fields = 1 } if fields < 0 { fields = 0 } prefixLen := 1 var n = prefixLen for i := 0; i <= fields; i++ { switch i { case 1: n += 20 } } key := make([]byte, n) for i := 0; i <= fields; i++ { switch i { case 0: copy(key, k.Prefix) case 1: copy(key[prefixLen:], k.ClaimHash) } } return key } func SupportAmountKeyUnpack(key []byte) *SupportAmountKey { prefixLen := 1 return &SupportAmountKey{ Prefix: key[:prefixLen], ClaimHash: key[prefixLen : prefixLen+20], } } func SupportAmountValueUnpack(value []byte) *SupportAmountValue { return &SupportAmountValue{ Amount: binary.BigEndian.Uint64(value), } } type ClaimToSupportKey struct { Prefix []byte `struct:"[1]byte" json:"prefix"` ClaimHash []byte `struct:"[20]byte" json:"claim_hash"` TxNum uint32 `json:"tx_num"` Position uint16 `json:"position"` } type ClaimToSupportValue struct { Amount uint64 `json:"amount"` } func (k *ClaimToSupportKey) PackKey() []byte { prefixLen := 1 // b'>20sLH' n := prefixLen + 20 + 4 + 2 key := make([]byte, n) copy(key, k.Prefix) copy(key[prefixLen:], k.ClaimHash[:20]) binary.BigEndian.PutUint32(key[prefixLen+20:], k.TxNum) binary.BigEndian.PutUint16(key[prefixLen+24:], k.Position) return key } func (v *ClaimToSupportValue) PackValue() []byte { value := make([]byte, 8) binary.BigEndian.PutUint64(value, v.Amount) return value } func (kv *ClaimToSupportKey) NumFields() int { return 3 } func (k *ClaimToSupportKey) PartialPack(fields int) []byte { // Limit fields between 0 and number of fields, we always at least need // the prefix, and we never need to iterate past the number of fields. if fields > 3 { fields = 3 } if fields < 0 { fields = 0 } // b'>4sLH' prefixLen := 1 var n = prefixLen for i := 0; i <= fields; i++ { switch i { case 1: n += 20 case 2: n += 4 case 3: n += 2 } } key := make([]byte, n) for i := 0; i <= fields; i++ { switch i { case 0: copy(key, k.Prefix) case 1: copy(key[prefixLen:], k.ClaimHash) case 2: binary.BigEndian.PutUint32(key[prefixLen+20:], k.TxNum) case 3: binary.BigEndian.PutUint16(key[prefixLen+24:], k.Position) } } return key } func ClaimToSupportKeyUnpack(key []byte) *ClaimToSupportKey { prefixLen := 1 return &ClaimToSupportKey{ Prefix: key[:prefixLen], ClaimHash: key[prefixLen : prefixLen+20], TxNum: binary.BigEndian.Uint32(key[prefixLen+20:]), Position: binary.BigEndian.Uint16(key[prefixLen+24:]), } } func ClaimToSupportValueUnpack(value []byte) *ClaimToSupportValue { return &ClaimToSupportValue{ Amount: binary.BigEndian.Uint64(value), } } type SupportToClaimKey struct { Prefix []byte `struct:"[1]byte" json:"prefix"` TxNum uint32 `json:"tx_num"` Position uint16 `json:"position"` } type SupportToClaimValue struct { ClaimHash []byte `struct:"[20]byte" json:"claim_hash"` } func (k *SupportToClaimKey) PackKey() []byte { prefixLen := 1 // b'>LH' n := prefixLen + 4 + 2 key := make([]byte, n) copy(key, k.Prefix) binary.BigEndian.PutUint32(key[prefixLen:], k.TxNum) binary.BigEndian.PutUint16(key[prefixLen+4:], k.Position) return key } func (v *SupportToClaimValue) PackValue() []byte { value := make([]byte, 20) copy(value, v.ClaimHash) return value } func (kv *SupportToClaimKey) NumFields() int { return 2 } func (k *SupportToClaimKey) PartialPack(fields int) []byte { // Limit fields between 0 and number of fields, we always at least need // the prefix, and we never need to iterate past the number of fields. if fields > 2 { fields = 2 } if fields < 0 { fields = 0 } prefixLen := 1 var n = prefixLen for i := 0; i <= fields; i++ { switch i { case 1: n += 4 case 2: n += 2 } } key := make([]byte, n) for i := 0; i <= fields; i++ { switch i { case 0: copy(key, k.Prefix) case 1: binary.BigEndian.PutUint32(key[prefixLen:], k.TxNum) case 2: binary.BigEndian.PutUint16(key[prefixLen+4:], k.Position) } } return key } func SupportToClaimKeyUnpack(key []byte) *SupportToClaimKey { prefixLen := 1 return &SupportToClaimKey{ Prefix: key[:prefixLen], TxNum: binary.BigEndian.Uint32(key[prefixLen:]), Position: binary.BigEndian.Uint16(key[prefixLen+4:]), } } func SupportToClaimValueUnpack(value []byte) *SupportToClaimValue { return &SupportToClaimValue{ ClaimHash: value[:20], } } type ClaimExpirationKey struct { Prefix []byte `struct:"[1]byte" json:"prefix"` Expiration uint32 `json:"expiration"` TxNum uint32 `json:"tx_num"` Position uint16 `json:"position"` } type ClaimExpirationValue struct { ClaimHash []byte `struct:"[20]byte" json:"claim_hash"` LengthEncodedNormalizedName // fields NormalizedNameLen, NormalizedName } func (k *ClaimExpirationKey) PackKey() []byte { prefixLen := 1 // b'>LLH' n := prefixLen + 4 + 4 + 2 key := make([]byte, n) copy(key, k.Prefix) binary.BigEndian.PutUint32(key[prefixLen:], k.Expiration) binary.BigEndian.PutUint32(key[prefixLen+4:], k.TxNum) binary.BigEndian.PutUint16(key[prefixLen+8:], k.Position) return key } func (v *ClaimExpirationValue) PackValue() []byte { nameLen := len(v.NormalizedName) n := 20 + 2 + nameLen value := make([]byte, n) copy(value, v.ClaimHash) binary.BigEndian.PutUint16(value[20:], uint16(nameLen)) copy(value[22:], []byte(v.NormalizedName)) return value } func (kv *ClaimExpirationKey) NumFields() int { return 3 } func (k *ClaimExpirationKey) PartialPack(fields int) []byte { // Limit fields between 0 and number of fields, we always at least need // the prefix, and we never need to iterate past the number of fields. if fields > 3 { fields = 3 } if fields < 0 { fields = 0 } // b'>4sLH' prefixLen := 1 var n = prefixLen for i := 0; i <= fields; i++ { switch i { case 1: n += 4 case 2: n += 4 case 3: n += 2 } } key := make([]byte, n) for i := 0; i <= fields; i++ { switch i { case 0: copy(key, k.Prefix) case 1: binary.BigEndian.PutUint32(key[prefixLen:], k.Expiration) case 2: binary.BigEndian.PutUint32(key[prefixLen+4:], k.TxNum) case 3: binary.BigEndian.PutUint16(key[prefixLen+8:], k.Position) } } return key } func ClaimExpirationKeyUnpack(key []byte) *ClaimExpirationKey { prefixLen := 1 return &ClaimExpirationKey{ Prefix: key[:prefixLen], Expiration: binary.BigEndian.Uint32(key[prefixLen:]), TxNum: binary.BigEndian.Uint32(key[prefixLen+4:]), Position: binary.BigEndian.Uint16(key[prefixLen+8:]), } } func ClaimExpirationValueUnpack(value []byte) *ClaimExpirationValue { nameLen := binary.BigEndian.Uint16(value[20:]) return &ClaimExpirationValue{ ClaimHash: value[:20], LengthEncodedNormalizedName: NewLengthEncodedNormalizedName(string(value[22 : 22+nameLen])), } } type ClaimTakeoverKey struct { Prefix []byte `struct:"[1]byte" json:"prefix"` LengthEncodedNormalizedName // fields NormalizedNameLen, NormalizedName } type ClaimTakeoverValue struct { ClaimHash []byte `struct:"[20]byte" json:"claim_hash"` Height uint32 `json:"height"` } func NewClaimTakeoverKey(normalizedName string) *ClaimTakeoverKey { return &ClaimTakeoverKey{ Prefix: []byte{ClaimTakeover}, LengthEncodedNormalizedName: NewLengthEncodedNormalizedName(normalizedName), } } func (v *ClaimTakeoverValue) String() string { return fmt.Sprintf( "%s(claim_hash=%s, height=%d)", reflect.TypeOf(v), hex.EncodeToString(v.ClaimHash), v.Height, ) } func (k *ClaimTakeoverKey) PackKey() []byte { prefixLen := 1 nameLen := len(k.NormalizedName) n := prefixLen + 2 + nameLen key := make([]byte, n) copy(key, k.Prefix) binary.BigEndian.PutUint16(key[prefixLen:], uint16(nameLen)) copy(key[prefixLen+2:], []byte(k.NormalizedName)) return key } func (v *ClaimTakeoverValue) PackValue() []byte { // b'>20sL' value := make([]byte, 24) copy(value, v.ClaimHash[:20]) binary.BigEndian.PutUint32(value[20:], uint32(v.Height)) return value } func (kv *ClaimTakeoverKey) NumFields() int { return 1 } func (k *ClaimTakeoverKey) PartialPack(fields int) []byte { // Limit fields between 0 and number of fields, we always at least need // the prefix, and we never need to iterate past the number of fields. if fields > 1 { fields = 1 } if fields < 0 { fields = 0 } prefixLen := 1 nameLen := len(k.NormalizedName) var n = prefixLen for i := 0; i <= fields; i++ { switch i { case 1: n += 2 + nameLen } } key := make([]byte, n) for i := 0; i <= fields; i++ { switch i { case 0: copy(key, k.Prefix) case 1: binary.BigEndian.PutUint16(key[prefixLen:], uint16(nameLen)) copy(key[prefixLen+2:], []byte(k.NormalizedName)) } } return key } func ClaimTakeoverKeyUnpack(key []byte) *ClaimTakeoverKey { prefixLen := 1 nameLen := binary.BigEndian.Uint16(key[prefixLen:]) return &ClaimTakeoverKey{ Prefix: key[:prefixLen], LengthEncodedNormalizedName: NewLengthEncodedNormalizedName(string(key[prefixLen+2 : prefixLen+2+int(nameLen)])), } } func ClaimTakeoverValueUnpack(value []byte) *ClaimTakeoverValue { return &ClaimTakeoverValue{ ClaimHash: value[:20], Height: binary.BigEndian.Uint32(value[20:]), } } type PendingActivationKey struct { Prefix []byte `struct:"[1]byte" json:"prefix"` Height uint32 `json:"height"` TxoType uint8 `json:"txo_type"` TxNum uint32 `json:"tx_num"` Position uint16 `json:"position"` } func (k *PendingActivationKey) IsSupport() bool { return k.TxoType == ActivatedSupportTXOType } func (k *PendingActivationKey) IsClaim() bool { return k.TxoType == ActivateClaimTXOType } type PendingActivationValue struct { ClaimHash []byte `struct:"[20]byte" json:"claim_hash"` LengthEncodedNormalizedName // fields NormalizedNameLen, NormalizedName } func (k *PendingActivationKey) PackKey() []byte { prefixLen := 1 // b'>LBLH' n := prefixLen + 4 + 1 + 4 + 2 key := make([]byte, n) copy(key, k.Prefix) binary.BigEndian.PutUint32(key[prefixLen:], k.Height) key[prefixLen+4] = k.TxoType binary.BigEndian.PutUint32(key[prefixLen+5:], k.TxNum) binary.BigEndian.PutUint16(key[prefixLen+9:], k.Position) return key } func (v *PendingActivationValue) PackValue() []byte { nameLen := len(v.NormalizedName) n := 20 + 2 + nameLen value := make([]byte, n) copy(value, v.ClaimHash[:20]) binary.BigEndian.PutUint16(value[20:], uint16(nameLen)) copy(value[22:], []byte(v.NormalizedName)) return value } func (kv *PendingActivationKey) NumFields() int { return 4 } func (k *PendingActivationKey) PartialPack(fields int) []byte { // Limit fields between 0 and number of fields, we always at least need // the prefix, and we never need to iterate past the number of fields. if fields > 4 { fields = 4 } if fields < 0 { fields = 0 } // b'>4sLH' prefixLen := 1 var n = prefixLen for i := 0; i <= fields; i++ { switch i { case 1: n += 4 case 2: n += 1 case 3: n += 4 case 4: n += 2 } } key := make([]byte, n) for i := 0; i <= fields; i++ { switch i { case 0: copy(key, k.Prefix) case 1: binary.BigEndian.PutUint32(key[prefixLen:], k.Height) case 2: key[prefixLen+4] = k.TxoType case 3: binary.BigEndian.PutUint32(key[prefixLen+5:], k.TxNum) case 4: binary.BigEndian.PutUint16(key[prefixLen+9:], k.Position) } } return key } func PendingActivationKeyUnpack(key []byte) *PendingActivationKey { prefixLen := 1 return &PendingActivationKey{ Prefix: key[:prefixLen], Height: binary.BigEndian.Uint32(key[prefixLen:]), TxoType: key[prefixLen+4], TxNum: binary.BigEndian.Uint32(key[prefixLen+5:]), Position: binary.BigEndian.Uint16(key[prefixLen+9:]), } } func PendingActivationValueUnpack(value []byte) *PendingActivationValue { nameLen := binary.BigEndian.Uint16(value[20:]) return &PendingActivationValue{ ClaimHash: value[:20], LengthEncodedNormalizedName: NewLengthEncodedNormalizedName(string(value[22 : 22+nameLen])), } } type ActivationKey struct { Prefix []byte `struct:"[1]byte" json:"prefix"` TxoType uint8 `json:"txo_type"` TxNum uint32 `json:"tx_num"` Position uint16 `json:"position"` } type ActivationValue struct { Height uint32 `json:"height"` ClaimHash []byte `struct:"[20]byte" json:"claim_hash"` LengthEncodedNormalizedName // fields NormalizedNameLen, NormalizedName } func NewActivationKey(txoType uint8, txNum uint32, position uint16) *ActivationKey { return &ActivationKey{ Prefix: []byte{ActivatedClaimAndSupport}, TxoType: txoType, TxNum: txNum, Position: position, } } func (k *ActivationKey) PackKey() []byte { prefixLen := 1 // b'>BLH' n := prefixLen + 1 + 4 + 2 key := make([]byte, n) copy(key, k.Prefix) copy(key[prefixLen:], []byte{k.TxoType}) binary.BigEndian.PutUint32(key[prefixLen+1:], k.TxNum) binary.BigEndian.PutUint16(key[prefixLen+5:], k.Position) return key } func (v *ActivationValue) PackValue() []byte { nameLen := len(v.NormalizedName) n := 4 + 20 + 2 + nameLen value := make([]byte, n) binary.BigEndian.PutUint32(value, v.Height) copy(value[4:], v.ClaimHash[:20]) binary.BigEndian.PutUint16(value[24:], uint16(nameLen)) copy(value[26:], []byte(v.NormalizedName)) return value } func (kv *ActivationKey) NumFields() int { return 3 } func (k *ActivationKey) PartialPack(fields int) []byte { // Limit fields between 0 and number of fields, we always at least need // the prefix, and we never need to iterate past the number of fields. if fields > 3 { fields = 3 } if fields < 0 { fields = 0 } prefixLen := 1 var n = prefixLen for i := 0; i <= fields; i++ { switch i { case 1: n += 1 case 2: n += 4 case 3: n += 2 } } key := make([]byte, n) for i := 0; i <= fields; i++ { switch i { case 0: copy(key, k.Prefix) case 1: key[prefixLen] = k.TxoType case 2: binary.BigEndian.PutUint32(key[prefixLen+1:], k.TxNum) case 3: binary.BigEndian.PutUint16(key[prefixLen+5:], k.Position) } } return key } func ActivationKeyUnpack(key []byte) *ActivationKey { prefixLen := 1 return &ActivationKey{ Prefix: key[:prefixLen], TxoType: key[prefixLen], TxNum: binary.BigEndian.Uint32(key[prefixLen+1:]), Position: binary.BigEndian.Uint16(key[prefixLen+5:]), } } func ActivationValueUnpack(value []byte) *ActivationValue { nameLen := binary.BigEndian.Uint16(value[24:]) return &ActivationValue{ Height: binary.BigEndian.Uint32(value), ClaimHash: value[4 : 20+4], LengthEncodedNormalizedName: NewLengthEncodedNormalizedName(string(value[26 : 26+nameLen])), } } type ActiveAmountKey struct { Prefix []byte `struct:"[1]byte" json:"prefix"` ClaimHash []byte `struct:"[20]byte" json:"claim_hash"` TxoType uint8 `json:"txo_type"` ActivationHeight uint32 `json:"activation_height"` TxNum uint32 `json:"tx_num"` Position uint16 `json:"position"` } type ActiveAmountValue struct { Amount uint64 `json:"amount"` } func NewActiveAmountKey(claimHash []byte, txoType uint8, activationHeight uint32) *ActiveAmountKey { return &ActiveAmountKey{ Prefix: []byte{ActiveAmount}, ClaimHash: claimHash, TxoType: txoType, ActivationHeight: activationHeight, } } func (k *ActiveAmountKey) PackKey() []byte { prefixLen := 1 // b'>20sBLLH' n := prefixLen + 20 + 1 + 4 + 4 + 2 key := make([]byte, n) copy(key, k.Prefix) copy(key[prefixLen:], k.ClaimHash[:20]) copy(key[prefixLen+20:], []byte{k.TxoType}) binary.BigEndian.PutUint32(key[prefixLen+20+1:], k.ActivationHeight) binary.BigEndian.PutUint32(key[prefixLen+20+1+4:], k.TxNum) binary.BigEndian.PutUint16(key[prefixLen+20+1+4+4:], k.Position) return key } func (v *ActiveAmountValue) PackValue() []byte { // b'>Q' value := make([]byte, 8) binary.BigEndian.PutUint64(value, v.Amount) return value } func (kv *ActiveAmountKey) NumFields() int { return 5 } func (k *ActiveAmountKey) PartialPack(fields int) []byte { // Limit fields between 0 and number of fields, we always at least need // the prefix, and we never need to iterate past the number of fields. if fields > 5 { fields = 5 } if fields < 0 { fields = 0 } prefixLen := 1 var n = prefixLen for i := 0; i <= fields; i++ { switch i { case 1: n += 20 case 2: n += 1 case 3: n += 4 case 4: n += 4 case 5: n += 2 } } key := make([]byte, n) for i := 0; i <= fields; i++ { switch i { case 0: copy(key, k.Prefix) case 1: copy(key[prefixLen:], k.ClaimHash) case 2: copy(key[prefixLen+20:], []byte{k.TxoType}) case 3: binary.BigEndian.PutUint32(key[prefixLen+20+1:], k.ActivationHeight) case 4: binary.BigEndian.PutUint32(key[prefixLen+20+1+4:], k.TxNum) case 5: binary.BigEndian.PutUint16(key[prefixLen+20+1+4+4:], k.Position) } } return key } func ActiveAmountKeyUnpack(key []byte) *ActiveAmountKey { prefixLen := 1 return &ActiveAmountKey{ Prefix: key[:prefixLen], ClaimHash: key[prefixLen : prefixLen+20], TxoType: uint8(key[prefixLen+20 : prefixLen+20+1][0]), ActivationHeight: binary.BigEndian.Uint32(key[prefixLen+20+1:]), TxNum: binary.BigEndian.Uint32(key[prefixLen+20+1+4:]), Position: binary.BigEndian.Uint16(key[prefixLen+20+1+4+4:]), } } func ActiveAmountValueUnpack(value []byte) *ActiveAmountValue { return &ActiveAmountValue{ Amount: binary.BigEndian.Uint64(value), } } type OnesComplementEffectiveAmount uint64 type BidOrderKey struct { Prefix []byte `struct:"[1]byte" json:"prefix"` LengthEncodedNormalizedName // fields NormalizedNameLen, NormalizedName EffectiveAmount OnesComplementEffectiveAmount `json:"effective_amount"` TxNum uint32 `json:"tx_num"` Position uint16 `json:"position"` } type BidOrderValue struct { ClaimHash []byte `struct:"[20]byte" json:"claim_hash"` } func NewBidOrderKey(normalizedName string) *BidOrderKey { return &BidOrderKey{ Prefix: []byte{BidOrder}, LengthEncodedNormalizedName: NewLengthEncodedNormalizedName(normalizedName), } } func (k *BidOrderKey) PackKey() []byte { prefixLen := 1 // 2 byte length field, plus number of bytes in name nameLen := len(k.NormalizedName) nameLenLen := 2 + nameLen // b'>QLH' n := prefixLen + nameLenLen + 8 + 4 + 2 key := make([]byte, n) copy(key, k.Prefix) binary.BigEndian.PutUint16(key[prefixLen:], uint16(nameLen)) copy(key[prefixLen+2:], []byte(k.NormalizedName)) binary.BigEndian.PutUint64(key[prefixLen+nameLenLen:], OnesCompTwiddle64-uint64(k.EffectiveAmount)) binary.BigEndian.PutUint32(key[prefixLen+nameLenLen+8:], k.TxNum) binary.BigEndian.PutUint16(key[prefixLen+nameLenLen+8+4:], k.Position) return key } func (v *BidOrderValue) PackValue() []byte { // b'>20s' value := make([]byte, 20) copy(value, v.ClaimHash[:20]) return value } func (kv *BidOrderKey) NumFields() int { return 4 } func (k *BidOrderKey) PartialPack(fields int) []byte { // Limit fields between 0 and number of fields, we always at least need // the prefix, and we never need to iterate past the number of fields. nameLen := len(k.NormalizedName) nameLenLen := 2 + nameLen if fields > 4 { fields = 4 } if fields < 0 { fields = 0 } prefixLen := 1 var n = prefixLen for i := 0; i <= fields; i++ { switch i { case 1: n += 2 + nameLen case 2: n += 8 case 3: n += 4 case 4: n += 2 } } key := make([]byte, n) for i := 0; i <= fields; i++ { switch i { case 0: copy(key, k.Prefix) case 1: binary.BigEndian.PutUint16(key[prefixLen:], uint16(nameLen)) copy(key[prefixLen+2:], []byte(k.NormalizedName)) case 2: binary.BigEndian.PutUint64(key[prefixLen+nameLenLen:], OnesCompTwiddle64-uint64(k.EffectiveAmount)) case 3: binary.BigEndian.PutUint32(key[prefixLen+nameLenLen+8:], k.TxNum) case 4: binary.BigEndian.PutUint16(key[prefixLen+nameLenLen+8+4:], k.Position) } } return key } func BidOrderKeyUnpack(key []byte) *BidOrderKey { prefixLen := 1 nameLen := binary.BigEndian.Uint16(key[prefixLen:]) return &BidOrderKey{ Prefix: key[:prefixLen], LengthEncodedNormalizedName: NewLengthEncodedNormalizedName(string(key[prefixLen+2 : prefixLen+2+int(nameLen)])), EffectiveAmount: OnesComplementEffectiveAmount(OnesCompTwiddle64 - binary.BigEndian.Uint64(key[prefixLen+2+int(nameLen):])), TxNum: binary.BigEndian.Uint32(key[prefixLen+2+int(nameLen)+8:]), Position: binary.BigEndian.Uint16(key[prefixLen+2+int(nameLen)+8+4:]), } } func BidOrderValueUnpack(value []byte) *BidOrderValue { return &BidOrderValue{ ClaimHash: value[:20], } } type RepostKey struct { Prefix []byte `struct:"[1]byte" json:"prefix"` ClaimHash []byte `struct:"[20]byte" json:"claim_hash"` } type RepostValue struct { RepostedClaimHash []byte `struct:"[20]byte" json:"reposted_claim_hash"` } func NewRepostKey(claimHash []byte) *RepostKey { return &RepostKey{ Prefix: []byte{Repost}, ClaimHash: claimHash, } } func (k *RepostKey) PackKey() []byte { prefixLen := 1 // b'>20s' n := prefixLen + 20 key := make([]byte, n) copy(key, k.Prefix) copy(key[prefixLen:], k.ClaimHash) return key } func (v *RepostValue) PackValue() []byte { // FIXME: Is there a limit to this length? n := len(v.RepostedClaimHash) value := make([]byte, n) copy(value, v.RepostedClaimHash) return value } func (kv *RepostKey) NumFields() int { return 1 } func (k *RepostKey) PartialPack(fields int) []byte { // Limit fields between 0 and number of fields, we always at least need // the prefix, and we never need to iterate past the number of fields. if fields > 1 { fields = 1 } if fields < 0 { fields = 0 } prefixLen := 1 var n = prefixLen for i := 0; i <= fields; i++ { switch i { case 1: n += 20 } } key := make([]byte, n) for i := 0; i <= fields; i++ { switch i { case 0: copy(key, k.Prefix) case 1: copy(key[prefixLen:], k.ClaimHash) } } return key } func RepostKeyUnpack(key []byte) *RepostKey { prefixLen := 1 return &RepostKey{ Prefix: key[:prefixLen], ClaimHash: key[prefixLen : prefixLen+20], } } func RepostValueUnpack(value []byte) *RepostValue { return &RepostValue{ RepostedClaimHash: value[:], } } type RepostedKey struct { Prefix []byte `struct:"[1]byte" json:"prefix"` RepostedClaimHash []byte `struct:"[20]byte" json:"reposted_claim_hash"` TxNum uint32 `json:"tx_num"` Position uint16 `json:"position"` } type RepostedValue struct { ClaimHash []byte `struct:"[20]byte" json:"claim_hash"` } func NewRepostedKey(claimHash []byte) *RepostedKey { return &RepostedKey{ Prefix: []byte{RepostedClaim}, RepostedClaimHash: claimHash, } } func (k *RepostedKey) PackKey() []byte { prefixLen := 1 // b'>20sLH' n := prefixLen + 20 + 4 + 2 key := make([]byte, n) copy(key, k.Prefix) copy(key[prefixLen:], k.RepostedClaimHash) binary.BigEndian.PutUint32(key[prefixLen+20:], k.TxNum) binary.BigEndian.PutUint16(key[prefixLen+24:], k.Position) return key } func (v *RepostedValue) PackValue() []byte { // b'>20s' value := make([]byte, 20) copy(value, v.ClaimHash) return value } func (kv *RepostedKey) NumFields() int { return 3 } func (k *RepostedKey) PartialPack(fields int) []byte { // Limit fields between 0 and number of fields, we always at least need // the prefix, and we never need to iterate past the number of fields. if fields > 3 { fields = 3 } if fields < 0 { fields = 0 } prefixLen := 1 var n = prefixLen for i := 0; i <= fields; i++ { switch i { case 1: n += 20 case 2: n += 4 case 3: n += 2 } } key := make([]byte, n) for i := 0; i <= fields; i++ { switch i { case 0: copy(key, k.Prefix) case 1: copy(key[prefixLen:], k.RepostedClaimHash) case 2: binary.BigEndian.PutUint32(key[prefixLen+20:], k.TxNum) case 3: binary.BigEndian.PutUint16(key[prefixLen+24:], k.Position) } } return key } func RepostedKeyUnpack(key []byte) *RepostedKey { prefixLen := 1 return &RepostedKey{ Prefix: key[:prefixLen], RepostedClaimHash: key[prefixLen : prefixLen+20], TxNum: binary.BigEndian.Uint32(key[prefixLen+20:]), Position: binary.BigEndian.Uint16(key[prefixLen+24:]), } } func RepostedValueUnpack(value []byte) *RepostedValue { return &RepostedValue{ ClaimHash: value[:20], } } type RepostedCountKey struct { Prefix []byte `struct:"[1]byte" json:"prefix"` ClaimHash []byte `struct:"[20]byte" json:"claim_hash"` } type RepostedCountValue struct { RepostedCount uint32 `json:"reposted_count"` } func (kv *RepostedCountKey) NumFields() int { return 1 } func (kv *RepostedCountKey) PartialPack(fields int) []byte { // b'>20s' n := len(kv.Prefix) + 20 buf := make([]byte, n) offset := 0 offset += copy(buf[offset:], kv.Prefix[:1]) if fields <= 0 { return buf[:offset] } offset += copy(buf[offset:], kv.ClaimHash[:20]) return buf[:offset] } func (kv *RepostedCountKey) PackKey() []byte { return kv.PartialPack(kv.NumFields()) } func (kv *RepostedCountKey) UnpackKey(buf []byte) { // b'>20s' offset := 0 kv.Prefix = buf[offset : offset+1] offset += 1 kv.ClaimHash = buf[offset : offset+20] offset += 20 } func (kv *RepostedCountValue) PackValue() []byte { // b'>L' n := 4 buf := make([]byte, n) offset := 0 binary.BigEndian.PutUint32(buf[offset:], kv.RepostedCount) offset += 4 return buf[:offset] } func (kv *RepostedCountValue) UnpackValue(buf []byte) { // b'>L' offset := 0 kv.RepostedCount = binary.BigEndian.Uint32(buf[offset:]) offset += 4 } type TouchedOrDeletedClaimKey struct { Prefix []byte `struct:"[1]byte" json:"prefix"` Height int32 `json:"height"` } type TouchedOrDeletedClaimValue struct { TouchedClaimsLen uint32 `struct:"sizeof=TouchedClaims"` DeletedClaimsLen uint32 `struct:"sizeof=DeletedClaims"` TouchedClaims [][]byte `struct:"[][20]byte" json:"touched_claims"` DeletedClaims [][]byte `struct:"[][20]byte" json:"deleted_claims"` } func (v *TouchedOrDeletedClaimValue) String() string { touchedSB := strings.Builder{} touchedLen := len(v.TouchedClaims) for i, claim := range v.TouchedClaims { touchedSB.WriteString(hex.EncodeToString(claim)) if i < touchedLen-1 { touchedSB.WriteString(",") } } deletedSB := strings.Builder{} deletedLen := len(v.DeletedClaims) for i, claim := range v.DeletedClaims { deletedSB.WriteString(hex.EncodeToString(claim)) if i < deletedLen-1 { deletedSB.WriteString(",") } } return fmt.Sprintf( "%s(touched_claims=%s, deleted_claims=%s)", reflect.TypeOf(v), touchedSB.String(), deletedSB.String(), ) } func (k *TouchedOrDeletedClaimKey) PackKey() []byte { prefixLen := 1 // b'>L' n := prefixLen + 4 key := make([]byte, n) copy(key, k.Prefix) binary.BigEndian.PutUint32(key[prefixLen:], uint32(k.Height)) return key } func (v *TouchedOrDeletedClaimValue) PackValue() []byte { var touchedLen, deletedLen uint32 = 0, 0 if v.TouchedClaims != nil { for _, claim := range v.TouchedClaims { if len(claim) != 20 { log.Println("TouchedOrDeletedClaimValue: claim not length 20?!?") return nil } } touchedLen = uint32(len(v.TouchedClaims)) } if v.DeletedClaims != nil { for _, claim := range v.DeletedClaims { if len(claim) != 20 { log.Println("TouchedOrDeletedClaimValue: claim not length 20?!?") return nil } } deletedLen = uint32(len(v.DeletedClaims)) } n := 4 + 4 + 20*touchedLen + 20*deletedLen value := make([]byte, n) binary.BigEndian.PutUint32(value, touchedLen) binary.BigEndian.PutUint32(value[4:], deletedLen) // These are sorted for consistency with the Python implementation sort.Slice(v.TouchedClaims, func(i, j int) bool { return bytes.Compare(v.TouchedClaims[i], v.TouchedClaims[j]) < 0 }) sort.Slice(v.DeletedClaims, func(i, j int) bool { return bytes.Compare(v.DeletedClaims[i], v.DeletedClaims[j]) < 0 }) var i = 8 for j := 0; j < int(touchedLen); j++ { copy(value[i:], v.TouchedClaims[j]) i += 20 } for j := 0; j < int(deletedLen); j++ { copy(value[i:], v.DeletedClaims[j]) i += 20 } return value } func (kv *TouchedOrDeletedClaimKey) NumFields() int { return 1 } func (k *TouchedOrDeletedClaimKey) PartialPack(fields int) []byte { // Limit fields between 0 and number of fields, we always at least need // the prefix, and we never need to iterate past the number of fields. if fields > 1 { fields = 1 } if fields < 0 { fields = 0 } prefixLen := 1 var n = prefixLen for i := 0; i <= fields; i++ { switch i { case 1: n += 4 } } key := make([]byte, n) for i := 0; i <= fields; i++ { switch i { case 0: copy(key, k.Prefix) case 1: binary.BigEndian.PutUint32(key[prefixLen:], uint32(k.Height)) } } return key } func TouchedOrDeletedClaimKeyUnpack(key []byte) *TouchedOrDeletedClaimKey { prefixLen := 1 return &TouchedOrDeletedClaimKey{ Prefix: key[:prefixLen], Height: int32(binary.BigEndian.Uint32(key[prefixLen:])), } } func TouchedOrDeletedClaimValueUnpack(value []byte) *TouchedOrDeletedClaimValue { touchedLen := binary.BigEndian.Uint32(value) deletedLen := binary.BigEndian.Uint32(value[4:]) touchedClaims := make([][]byte, touchedLen) deletedClaims := make([][]byte, deletedLen) var j = 8 for i := 0; i < int(touchedLen); i++ { touchedClaims[i] = value[j : j+20] j += 20 } for i := 0; i < int(deletedLen); i++ { deletedClaims[i] = value[j : j+20] j += 20 } return &TouchedOrDeletedClaimValue{ TouchedClaimsLen: touchedLen, DeletedClaimsLen: deletedLen, TouchedClaims: touchedClaims, DeletedClaims: deletedClaims, } } func (k *UTXOKey) String() string { return fmt.Sprintf( "%s(hashX=%s, tx_num=%d, nout=%d)", reflect.TypeOf(k), hex.EncodeToString(k.HashX), k.TxNum, k.Nout, ) } func (k *UTXOKey) PackKey() []byte { prefixLen := 1 // b'>11sLH' n := prefixLen + 11 + 4 + 2 key := make([]byte, n) copy(key, k.Prefix) copy(key[prefixLen:], k.HashX) binary.BigEndian.PutUint32(key[prefixLen+11:], k.TxNum) binary.BigEndian.PutUint16(key[prefixLen+15:], k.Nout) return key } func (k *UTXOValue) PackValue() []byte { value := make([]byte, 8) binary.BigEndian.PutUint64(value, k.Amount) return value } func (kv *UTXOKey) NumFields() int { return 3 } // UTXOKeyPackPartial packs a variable number of fields for a UTXOKey into // a byte array. func (k *UTXOKey) PartialPack(fields int) []byte { // Limit fields between 0 and number of fields, we always at least need // the prefix, and we never need to iterate past the number of fields. if fields > 3 { fields = 3 } if fields < 0 { fields = 0 } // b'>11sLH' prefixLen := 1 var n = prefixLen for i := 0; i <= fields; i++ { switch i { case 1: n += 11 case 2: n += 4 case 3: n += 2 } } key := make([]byte, n) for i := 0; i <= fields; i++ { switch i { case 0: copy(key, k.Prefix) case 1: copy(key[prefixLen:], k.HashX) case 2: binary.BigEndian.PutUint32(key[prefixLen+11:], k.TxNum) case 3: binary.BigEndian.PutUint16(key[prefixLen+15:], k.Nout) } } return key } func UTXOKeyUnpack(key []byte) *UTXOKey { prefixLen := 1 return &UTXOKey{ Prefix: key[:prefixLen], HashX: key[prefixLen : prefixLen+11], TxNum: binary.BigEndian.Uint32(key[prefixLen+11:]), Nout: binary.BigEndian.Uint16(key[prefixLen+15:]), } } func UTXOValueUnpack(value []byte) *UTXOValue { return &UTXOValue{ Amount: binary.BigEndian.Uint64(value), } } type TrendingNotificationKey struct { Prefix []byte `struct:"[1]byte" json:"prefix"` Height uint32 `json:"height"` ClaimHash []byte `struct:"[20]byte" json:"claim_hash"` } type TrendingNotificationValue struct { PreviousAmount uint64 `json:"previous_amount"` NewAmount uint64 `json:"new_amount"` } func (kv *TrendingNotificationKey) NumFields() int { return 2 } func (kv *TrendingNotificationKey) PartialPack(fields int) []byte { // b'>L20s' n := len(kv.Prefix) + 4 + 20 buf := make([]byte, n) offset := 0 offset += copy(buf, kv.Prefix[offset:]) if fields <= 0 { return buf[:offset] } binary.BigEndian.PutUint32(buf[offset:], kv.Height) offset += 4 if fields -= 1; fields <= 0 { return buf[:offset] } offset += copy(buf[offset:], kv.ClaimHash[:20]) return buf[:offset] } func (kv *TrendingNotificationKey) PackKey() []byte { return kv.PartialPack(kv.NumFields()) } func (kv *TrendingNotificationKey) UnpackKey(buf []byte) { // b'>L20s' offset := 0 kv.Prefix = buf[offset : offset+1] offset += 1 kv.Height = binary.BigEndian.Uint32(buf[offset:]) offset += 4 kv.ClaimHash = buf[offset : offset+20] offset += 20 } func (kv *TrendingNotificationValue) PackValue() []byte { // b'>QQ' n := 8 + 8 buf := make([]byte, n) offset := 0 binary.BigEndian.PutUint64(buf[offset:], kv.PreviousAmount) offset += 8 binary.BigEndian.PutUint64(buf[offset:], kv.NewAmount) offset += 8 return buf } func (kv *TrendingNotificationValue) UnpackValue(buf []byte) { // b'>QQ' offset := 0 kv.PreviousAmount = binary.BigEndian.Uint64(buf[offset:]) offset += 8 kv.NewAmount = binary.BigEndian.Uint64(buf[offset:]) offset += 8 } type TxKey = MempoolTxKey type TxValue = MempoolTxValue type MempoolTxKey struct { Prefix []byte `struct:"[1]byte" json:"prefix"` TxHash *chainhash.Hash `struct:"*[32]byte" json:"tx_hash"` } type MempoolTxValue struct { RawTx []byte `struct-while:"!_eof" json:"raw_tx"` } func (kv *MempoolTxKey) NumFields() int { return 1 } func (kv *MempoolTxKey) PartialPack(fields int) []byte { // b'>32s' n := len(kv.Prefix) + 32 buf := make([]byte, n) offset := 0 offset += copy(buf[offset:], kv.Prefix[:1]) if fields <= 0 { return buf[:offset] } offset += copy(buf[offset:], kv.TxHash[:32]) return buf[:offset] } func (kv *MempoolTxKey) PackKey() []byte { return kv.PartialPack(kv.NumFields()) } func (kv *MempoolTxKey) UnpackKey(buf []byte) { // b'>32s' offset := 0 kv.Prefix = buf[offset : offset+1] offset += 1 kv.TxHash = (*chainhash.Hash)(buf[offset : offset+32]) offset += 32 } func (kv *MempoolTxValue) PackValue() []byte { // variable length bytes n := len(kv.RawTx) buf := make([]byte, n) offset := 0 offset += copy(buf, kv.RawTx) return buf } func (kv *MempoolTxValue) UnpackValue(buf []byte) { // variable length bytes offset := 0 kv.RawTx = buf[:] offset += len(buf) } type TouchedHashXKey struct { Prefix []byte `struct:"[1]byte" json:"prefix"` Height uint32 `json:"height"` } type TouchedHashXValue struct { TouchedHashXs [][]byte `struct:"[][11]byte" struct-while:"!_eof" json:"touched_hashXs"` } func (kv *TouchedHashXKey) NumFields() int { return 1 } func (kv *TouchedHashXKey) PartialPack(fields int) []byte { // b'>L' n := len(kv.Prefix) + 4 buf := make([]byte, n) offset := 0 offset += copy(buf[offset:], kv.Prefix[:1]) if fields <= 0 { return buf[:offset] } binary.BigEndian.PutUint32(buf[offset:], kv.Height) offset += 4 return buf[:offset] } func (kv *TouchedHashXKey) PackKey() []byte { return kv.PartialPack(kv.NumFields()) } func (kv *TouchedHashXKey) UnpackKey(buf []byte) { // b'>L' offset := 0 kv.Prefix = buf[offset : offset+1] offset += 1 kv.Height = binary.BigEndian.Uint32(buf[offset:]) offset += 4 } func (kv *TouchedHashXValue) PackValue() []byte { // variable length bytes n := len(kv.TouchedHashXs) * 11 buf := make([]byte, n) offset := 0 for i := range kv.TouchedHashXs { offset += copy(buf[offset:], kv.TouchedHashXs[i][:11]) } return buf } func (kv *TouchedHashXValue) UnpackValue(buf []byte) { // variable length bytes n := len(buf) kv.TouchedHashXs = make([][]byte, n/11) for i, offset := 0, 0; offset+11 <= n; i, offset = i+1, offset+11 { kv.TouchedHashXs[i] = buf[offset : offset+11] } } type HashXStatusKey struct { Prefix []byte `struct:"[1]byte" json:"prefix"` HashX []byte `struct:"[20]byte" json:"hashX"` } type HashXStatusValue struct { Status []byte `struct:"[32]byte" json:"status"` } func (kv *HashXStatusKey) NumFields() int { return 1 } func (kv *HashXStatusKey) PartialPack(fields int) []byte { // b'>20s' n := len(kv.Prefix) + 20 buf := make([]byte, n) offset := 0 offset += copy(buf[offset:], kv.Prefix[:1]) if fields <= 0 { return buf[:offset] } offset += copy(buf[offset:], kv.HashX[:20]) return buf[:offset] } func (kv *HashXStatusKey) PackKey() []byte { return kv.PartialPack(kv.NumFields()) } func (kv *HashXStatusKey) UnpackKey(buf []byte) { // b'>20s' offset := 0 kv.Prefix = buf[offset : offset+1] offset += 1 kv.HashX = buf[offset : offset+20] offset += 20 } func (kv *HashXStatusValue) PackValue() []byte { // b'32s' n := 32 buf := make([]byte, n) offset := 0 offset += copy(buf[offset:], kv.Status[:32]) return buf } func (kv *HashXStatusValue) UnpackValue(buf []byte) { // b'32s' offset := 0 kv.Status = buf[offset : offset+32] offset += 32 } type HashXMempoolStatusKey = HashXStatusKey type HashXMempoolStatusValue = HashXStatusValue type EffectiveAmountKey struct { Prefix []byte `struct:"[1]byte" json:"prefix"` ClaimHash []byte `struct:"[20]byte" json:"claim_hash"` } type EffectiveAmountValue struct { ActivatedSum uint64 `json:"activated_sum"` ActivatedSupportSum uint64 `json:"activated_support_sum"` } func (kv *EffectiveAmountKey) NumFields() int { return 1 } func (kv *EffectiveAmountKey) PartialPack(fields int) []byte { // b'>20s' n := len(kv.Prefix) + 20 buf := make([]byte, n) offset := 0 offset += copy(buf[offset:], kv.Prefix[:1]) if fields <= 0 { return buf[:offset] } offset += copy(buf[offset:], kv.ClaimHash[:20]) return buf[:offset] } func (kv *EffectiveAmountKey) PackKey() []byte { return kv.PartialPack(kv.NumFields()) } func (kv *EffectiveAmountKey) UnpackKey(buf []byte) { // b'>20s' offset := 0 kv.Prefix = buf[offset : offset+1] offset += 1 kv.ClaimHash = buf[offset : offset+20] offset += 20 } func (kv *EffectiveAmountValue) PackValue() []byte { // b'>QQ' n := 8 + 8 buf := make([]byte, n) offset := 0 binary.BigEndian.PutUint64(buf[offset:], kv.ActivatedSum) offset += 8 binary.BigEndian.PutUint64(buf[offset:], kv.ActivatedSupportSum) offset += 8 return buf[:offset] } func (kv *EffectiveAmountValue) UnpackValue(buf []byte) { // b'>QQ' offset := 0 kv.ActivatedSum = binary.BigEndian.Uint64(buf[offset:]) offset += 8 kv.ActivatedSupportSum = binary.BigEndian.Uint64(buf[offset:]) offset += 8 } func UnpackGenericKey(key []byte) (BaseKey, error) { if len(key) == 0 { return nil, fmt.Errorf("key length zero") } // Look up the prefix metadata, and use the registered function(s) // to create and unpack key of appropriate type. t, ok := prefixRegistry[key[0]] if !ok { return nil, fmt.Errorf("unpack key function for %v not implemented", key[0]) } if t.newKeyUnpack != nil { // Type provides KeyUnpack() function. return t.newKeyUnpack(key).(BaseKey), nil } if t.newKey != nil { // Type provides a new function. k := t.newKey() unpacker, ok := k.(KeyUnpacker) if ok { unpacker.UnpackKey(key) return unpacker.(BaseKey), nil } } return nil, fmt.Errorf("unpack key function for %v not implemented", key[0]) } func UnpackGenericValue(key, value []byte) (BaseValue, error) { if len(key) == 0 { return nil, fmt.Errorf("key length zero") } if len(value) == 0 { return nil, fmt.Errorf("value length zero") } // Look up the prefix metadata, and use the registered function(s) // to create and unpack value of appropriate type. t, ok := prefixRegistry[key[0]] if !ok { return nil, fmt.Errorf("unpack value function for %v not implemented", key[0]) } if t.newValueUnpack != nil { // Type provides ValueUnpack() function. return t.newValueUnpack(value).(BaseValue), nil } if t.newValue != nil { // Type provides a new function. k := t.newValue() unpacker, ok := k.(ValueUnpacker) if ok { unpacker.UnpackValue(value) return unpacker.(BaseValue), nil } } return nil, fmt.Errorf("unpack key function for %v not implemented", key[0]) } func PackPartialGenericKey(key BaseKey, fields int) ([]byte, error) { if key == nil { return nil, fmt.Errorf("key is nil") } return key.PartialPack(fields), nil } func PackGenericKey(key BaseKey) ([]byte, error) { if key == nil { return nil, fmt.Errorf("key is nil") } return key.PackKey(), nil } func PackGenericValue(value BaseValue) ([]byte, error) { if value == nil { return nil, fmt.Errorf("value is nil") } return value.PackValue(), nil } // Metadata associated with each prefix/table. Currently used to // implement generic unpacking. type prefixMeta struct { newKey func() interface{} newValue func() interface{} newKeyUnpack func([]byte) interface{} newValueUnpack func([]byte) interface{} API *SerializationAPI } var prefixRegistry = map[byte]prefixMeta{ ClaimToSupport: { newKey: func() interface{} { return &ClaimToSupportKey{Prefix: []byte{ClaimToSupport}} }, newValue: func() interface{} { return &ClaimToSupportValue{} }, newKeyUnpack: func(buf []byte) interface{} { return ClaimToSupportKeyUnpack(buf) }, newValueUnpack: func(buf []byte) interface{} { return ClaimToSupportValueUnpack(buf) }, }, SupportToClaim: { newKey: func() interface{} { return &SupportToClaimKey{Prefix: []byte{SupportToClaim}} }, newValue: func() interface{} { return &SupportToClaimValue{} }, newKeyUnpack: func(buf []byte) interface{} { return SupportToClaimKeyUnpack(buf) }, newValueUnpack: func(buf []byte) interface{} { return SupportToClaimValueUnpack(buf) }, }, ClaimToTXO: { newKey: func() interface{} { return &ClaimToTXOKey{Prefix: []byte{ClaimToTXO}} }, newValue: func() interface{} { return &ClaimToTXOValue{} }, newKeyUnpack: func(buf []byte) interface{} { return ClaimToTXOKeyUnpack(buf) }, newValueUnpack: func(buf []byte) interface{} { return ClaimToTXOValueUnpack(buf) }, }, TXOToClaim: { newKey: func() interface{} { return &TXOToClaimKey{Prefix: []byte{TXOToClaim}} }, newValue: func() interface{} { return &TXOToClaimValue{} }, newKeyUnpack: func(buf []byte) interface{} { return TXOToClaimKeyUnpack(buf) }, newValueUnpack: func(buf []byte) interface{} { return TXOToClaimValueUnpack(buf) }, }, ClaimToChannel: { newKey: func() interface{} { return &ClaimToChannelKey{Prefix: []byte{ClaimToChannel}} }, newValue: func() interface{} { return &ClaimToChannelValue{} }, newKeyUnpack: func(buf []byte) interface{} { return ClaimToChannelKeyUnpack(buf) }, newValueUnpack: func(buf []byte) interface{} { return ClaimToChannelValueUnpack(buf) }, }, ChannelToClaim: { newKey: func() interface{} { return &ChannelToClaimKey{Prefix: []byte{ChannelToClaim}} }, newValue: func() interface{} { return &ChannelToClaimValue{} }, newKeyUnpack: func(buf []byte) interface{} { return ChannelToClaimKeyUnpack(buf) }, newValueUnpack: func(buf []byte) interface{} { return ChannelToClaimValueUnpack(buf) }, }, ClaimShortIdPrefix: { newKey: func() interface{} { return &ClaimShortIDKey{Prefix: []byte{ClaimShortIdPrefix}} }, newValue: func() interface{} { return &ClaimShortIDValue{} }, newKeyUnpack: func(buf []byte) interface{} { return ClaimShortIDKeyUnpack(buf) }, newValueUnpack: func(buf []byte) interface{} { return ClaimShortIDValueUnpack(buf) }, }, BidOrder: { newKey: func() interface{} { return &BidOrderKey{Prefix: []byte{BidOrder}} }, newValue: func() interface{} { return &BidOrderValue{} }, newKeyUnpack: func(buf []byte) interface{} { return BidOrderKeyUnpack(buf) }, newValueUnpack: func(buf []byte) interface{} { return BidOrderValueUnpack(buf) }, }, ClaimExpiration: { newKey: func() interface{} { return &ClaimExpirationKey{Prefix: []byte{ClaimExpiration}} }, newValue: func() interface{} { return &ClaimExpirationValue{} }, newKeyUnpack: func(buf []byte) interface{} { return ClaimExpirationKeyUnpack(buf) }, newValueUnpack: func(buf []byte) interface{} { return ClaimExpirationValueUnpack(buf) }, }, ClaimTakeover: { newKey: func() interface{} { return &ClaimTakeoverKey{Prefix: []byte{ClaimTakeover}} }, newValue: func() interface{} { return &ClaimTakeoverValue{} }, newKeyUnpack: func(buf []byte) interface{} { return ClaimTakeoverKeyUnpack(buf) }, newValueUnpack: func(buf []byte) interface{} { return ClaimTakeoverValueUnpack(buf) }, }, PendingActivation: { newKey: func() interface{} { return &PendingActivationKey{Prefix: []byte{PendingActivation}} }, newValue: func() interface{} { return &PendingActivationValue{} }, newKeyUnpack: func(buf []byte) interface{} { return PendingActivationKeyUnpack(buf) }, newValueUnpack: func(buf []byte) interface{} { return PendingActivationValueUnpack(buf) }, }, ActivatedClaimAndSupport: { newKey: func() interface{} { return &ActivationKey{Prefix: []byte{ActivatedClaimAndSupport}} }, newValue: func() interface{} { return &ActivationValue{} }, newKeyUnpack: func(buf []byte) interface{} { return ActivationKeyUnpack(buf) }, newValueUnpack: func(buf []byte) interface{} { return ActivationValueUnpack(buf) }, }, ActiveAmount: { newKey: func() interface{} { return &ActiveAmountKey{Prefix: []byte{ActiveAmount}} }, newValue: func() interface{} { return &ActiveAmountValue{} }, newKeyUnpack: func(buf []byte) interface{} { return ActiveAmountKeyUnpack(buf) }, newValueUnpack: func(buf []byte) interface{} { return ActiveAmountValueUnpack(buf) }, }, Repost: { newKey: func() interface{} { return &RepostKey{Prefix: []byte{Repost}} }, newValue: func() interface{} { return &RepostValue{} }, newKeyUnpack: func(buf []byte) interface{} { return RepostKeyUnpack(buf) }, newValueUnpack: func(buf []byte) interface{} { return RepostValueUnpack(buf) }, }, RepostedClaim: { newKey: func() interface{} { return &RepostedKey{Prefix: []byte{RepostedClaim}} }, newValue: func() interface{} { return &RepostedValue{} }, newKeyUnpack: func(buf []byte) interface{} { return RepostedKeyUnpack(buf) }, newValueUnpack: func(buf []byte) interface{} { return RepostedValueUnpack(buf) }, }, Undo: { newKey: func() interface{} { return &UndoKey{Prefix: []byte{Undo}} }, newValue: func() interface{} { return &UndoValue{} }, newKeyUnpack: func(buf []byte) interface{} { return UndoKeyUnpack(buf) }, newValueUnpack: func(buf []byte) interface{} { return UndoValueUnpack(buf) }, }, ClaimDiff: { newKey: func() interface{} { return &TouchedOrDeletedClaimKey{Prefix: []byte{ClaimDiff}} }, newValue: func() interface{} { return &TouchedOrDeletedClaimValue{} }, newKeyUnpack: func(buf []byte) interface{} { return TouchedOrDeletedClaimKeyUnpack(buf) }, newValueUnpack: func(buf []byte) interface{} { return TouchedOrDeletedClaimValueUnpack(buf) }, }, Tx: { newKey: func() interface{} { return &TxKey{Prefix: []byte{Tx}} }, newValue: func() interface{} { return &TxValue{} }, }, BlockHash: { newKey: func() interface{} { return &BlockHashKey{Prefix: []byte{BlockHash}} }, newValue: func() interface{} { return &BlockHashValue{} }, newKeyUnpack: func(buf []byte) interface{} { return BlockHashKeyUnpack(buf) }, newValueUnpack: func(buf []byte) interface{} { return BlockHashValueUnpack(buf) }, }, Header: { newKey: func() interface{} { return &BlockHeaderKey{Prefix: []byte{Header}} }, newValue: func() interface{} { return &BlockHeaderValue{} }, newKeyUnpack: func(buf []byte) interface{} { return BlockHeaderKeyUnpack(buf) }, newValueUnpack: func(buf []byte) interface{} { return BlockHeaderValueUnpack(buf) }, }, TxNum: { newKey: func() interface{} { return &TxNumKey{Prefix: []byte{TxNum}} }, newValue: func() interface{} { return &TxNumValue{} }, newKeyUnpack: func(buf []byte) interface{} { return TxNumKeyUnpack(buf) }, newValueUnpack: func(buf []byte) interface{} { return TxNumValueUnpack(buf) }, }, TxCount: { newKey: func() interface{} { return &TxCountKey{Prefix: []byte{TxCount}} }, newValue: func() interface{} { return &TxCountValue{} }, newKeyUnpack: func(buf []byte) interface{} { return TxCountKeyUnpack(buf) }, newValueUnpack: func(buf []byte) interface{} { return TxCountValueUnpack(buf) }, }, TxHash: { newKey: func() interface{} { return &TxHashKey{Prefix: []byte{TxHash}} }, newValue: func() interface{} { return &TxHashValue{} }, newKeyUnpack: func(buf []byte) interface{} { return TxHashKeyUnpack(buf) }, newValueUnpack: func(buf []byte) interface{} { return TxHashValueUnpack(buf) }, }, UTXO: { newKey: func() interface{} { return &UTXOKey{Prefix: []byte{UTXO}} }, newValue: func() interface{} { return &UTXOValue{} }, newKeyUnpack: func(buf []byte) interface{} { return UTXOKeyUnpack(buf) }, newValueUnpack: func(buf []byte) interface{} { return UTXOValueUnpack(buf) }, }, HashXUTXO: { newKey: func() interface{} { return &HashXUTXOKey{Prefix: []byte{HashXUTXO}} }, newValue: func() interface{} { return &HashXUTXOValue{} }, newKeyUnpack: func(buf []byte) interface{} { return HashXUTXOKeyUnpack(buf) }, newValueUnpack: func(buf []byte) interface{} { return HashXUTXOValueUnpack(buf) }, }, HashXHistory: { newKey: func() interface{} { return &HashXHistoryKey{Prefix: []byte{HashXHistory}} }, newValue: func() interface{} { return &HashXHistoryValue{} }, newKeyUnpack: func(buf []byte) interface{} { return HashXHistoryKeyUnpack(buf) }, newValueUnpack: func(buf []byte) interface{} { return HashXHistoryValueUnpack(buf) }, }, DBState: { newKey: func() interface{} { return &DBStateKey{Prefix: []byte{DBState}} }, newValue: func() interface{} { return &DBStateValue{} }, newKeyUnpack: func(buf []byte) interface{} { return DBStateKeyUnpack(buf) }, newValueUnpack: func(buf []byte) interface{} { return DBStateValueUnpack(buf) }, }, ChannelCount: { newKey: func() interface{} { return &ChannelCountKey{Prefix: []byte{ChannelCount}} }, newValue: func() interface{} { return &ChannelCountValue{} }, newKeyUnpack: func(buf []byte) interface{} { return ChannelCountKeyUnpack(buf) }, newValueUnpack: func(buf []byte) interface{} { return ChannelCountValueUnpack(buf) }, }, SupportAmount: { newKey: func() interface{} { return &SupportAmountKey{Prefix: []byte{SupportAmount}} }, newValue: func() interface{} { return &SupportAmountValue{} }, newKeyUnpack: func(buf []byte) interface{} { return SupportAmountKeyUnpack(buf) }, newValueUnpack: func(buf []byte) interface{} { return SupportAmountValueUnpack(buf) }, }, BlockTXs: { newKey: func() interface{} { return &BlockTxsKey{Prefix: []byte{BlockTXs}} }, newValue: func() interface{} { return &BlockTxsValue{} }, newKeyUnpack: func(buf []byte) interface{} { return BlockTxsKeyUnpack(buf) }, newValueUnpack: func(buf []byte) interface{} { return BlockTxsValueUnpack(buf) }, }, TrendingNotifications: { newKey: func() interface{} { return &TrendingNotificationKey{Prefix: []byte{TrendingNotifications}} }, newValue: func() interface{} { return &TrendingNotificationValue{} }, }, MempoolTx: { newKey: func() interface{} { return &MempoolTxKey{Prefix: []byte{MempoolTx}} }, newValue: func() interface{} { return &MempoolTxValue{} }, }, TouchedHashX: { newKey: func() interface{} { return &TouchedHashXKey{Prefix: []byte{TouchedHashX}} }, newValue: func() interface{} { return &TouchedHashXValue{} }, }, HashXStatus: { newKey: func() interface{} { return &HashXStatusKey{Prefix: []byte{HashXStatus}} }, newValue: func() interface{} { return &HashXStatusValue{} }, }, HashXMempoolStatus: { newKey: func() interface{} { return &HashXMempoolStatusKey{Prefix: []byte{HashXMempoolStatus}} }, newValue: func() interface{} { return &HashXMempoolStatusValue{} }, }, RepostedCount: { newKey: func() interface{} { return &RepostedCountKey{Prefix: []byte{RepostedCount}} }, newValue: func() interface{} { return &RepostedCountValue{} }, }, EffectiveAmount: { newKey: func() interface{} { return &EffectiveAmountKey{Prefix: []byte{EffectiveAmount}} }, newValue: func() interface{} { return &EffectiveAmountValue{} }, }, }