Add more special handling of DBStateValue.Genesis hash.

This commit is contained in:
Jonathan Moody 2022-11-30 16:37:18 -06:00
parent 829a2682ed
commit ee95fea47c
3 changed files with 53 additions and 7 deletions

View file

@ -7,6 +7,7 @@ import (
"strings" "strings"
"github.com/go-restruct/restruct" "github.com/go-restruct/restruct"
"github.com/lbryio/herald.go/internal"
"github.com/lbryio/lbcd/chaincfg/chainhash" "github.com/lbryio/lbcd/chaincfg/chainhash"
) )
@ -59,6 +60,34 @@ func (kv *BlockTxsValue) Unpack(buf []byte, order binary.ByteOrder) ([]byte, err
return buf[offset:], nil return buf[offset:], nil
} }
// Struct BigEndianChainHash is a chainhash.Hash stored in external
// byte-order (opposite of other 32 byte chainhash.Hash values). In order
// to reuse chainhash.Hash we need to correct the byte-order.
// Currently this type is used for field Genesis of DBStateValue.
func (kv *BigEndianChainHash) SizeOf() int {
return chainhash.HashSize
}
func (kv *BigEndianChainHash) Pack(buf []byte, order binary.ByteOrder) ([]byte, error) {
offset := 0
hash := kv.CloneBytes()
// HACK: Instances of chainhash.Hash use the internal byte-order.
// Python scribe writes bytes of genesis hash in external byte-order.
internal.ReverseBytesInPlace(hash)
offset += copy(buf[offset:chainhash.HashSize], hash[:])
return buf[offset:], nil
}
func (kv *BigEndianChainHash) Unpack(buf []byte, order binary.ByteOrder) ([]byte, error) {
offset := 0
offset += copy(kv.Hash[:], buf[offset:32])
// HACK: Instances of chainhash.Hash use the internal byte-order.
// Python scribe writes bytes of genesis hash in external byte-order.
internal.ReverseBytesInPlace(kv.Hash[:])
return buf[offset:], nil
}
func genericNew(prefix []byte, key bool) (interface{}, error) { func genericNew(prefix []byte, key bool) (interface{}, error) {
t, ok := prefixRegistry[prefix[0]] t, ok := prefixRegistry[prefix[0]]
if !ok { if !ok {

View file

@ -182,12 +182,25 @@ func NewLengthEncodedPartialClaimId(s string) LengthEncodedPartialClaimId {
} }
} }
type BigEndianChainHash struct {
chainhash.Hash
}
func NewBigEndianChainHash(hash *chainhash.Hash) BigEndianChainHash {
if hash != nil {
return BigEndianChainHash{
*hash,
}
}
return BigEndianChainHash{}
}
type DBStateKey struct { type DBStateKey struct {
Prefix []byte `struct:"[1]byte" json:"prefix"` Prefix []byte `struct:"[1]byte" json:"prefix"`
} }
type DBStateValue struct { type DBStateValue struct {
Genesis *chainhash.Hash Genesis BigEndianChainHash
Height uint32 Height uint32
TxCount uint32 TxCount uint32
Tip *chainhash.Hash Tip *chainhash.Hash
@ -203,7 +216,7 @@ type DBStateValue struct {
func NewDBStateValue() *DBStateValue { func NewDBStateValue() *DBStateValue {
return &DBStateValue{ return &DBStateValue{
Genesis: new(chainhash.Hash), Genesis: NewBigEndianChainHash(nil),
Height: 0, Height: 0,
TxCount: 0, TxCount: 0,
Tip: new(chainhash.Hash), Tip: new(chainhash.Hash),
@ -237,7 +250,11 @@ func (v *DBStateValue) PackValue() []byte {
// b'>32sLL32sLLBBlllL' // b'>32sLL32sLLBBlllL'
n := 32 + 4 + 4 + 32 + 4 + 4 + 1 + 1 + 4 + 4 + 4 + 4 n := 32 + 4 + 4 + 32 + 4 + 4 + 1 + 1 + 4 + 4 + 4 + 4
value := make([]byte, n) value := make([]byte, n)
copy(value, v.Genesis[:32]) genesis := v.Genesis.CloneBytes()
// HACK: Instances of chainhash.Hash use the internal byte-order.
// Python scribe writes bytes of genesis hash in external byte-order.
internal.ReverseBytesInPlace(genesis)
copy(value, genesis[:32])
binary.BigEndian.PutUint32(value[32:], v.Height) binary.BigEndian.PutUint32(value[32:], v.Height)
binary.BigEndian.PutUint32(value[32+4:], v.TxCount) binary.BigEndian.PutUint32(value[32+4:], v.TxCount)
copy(value[32+4+4:], v.Tip[:32]) copy(value[32+4+4:], v.Tip[:32])
@ -286,7 +303,7 @@ func DBStateValueUnpack(value []byte) *DBStateValue {
// Instances of chainhash.Hash should use the internal byte-order. // Instances of chainhash.Hash should use the internal byte-order.
internal.ReverseBytesInPlace(genesis[:]) internal.ReverseBytesInPlace(genesis[:])
x := &DBStateValue{ x := &DBStateValue{
Genesis: genesis, Genesis: NewBigEndianChainHash(genesis),
Height: binary.BigEndian.Uint32(value[32:]), Height: binary.BigEndian.Uint32(value[32:]),
TxCount: binary.BigEndian.Uint32(value[32+4:]), TxCount: binary.BigEndian.Uint32(value[32+4:]),
Tip: tip, Tip: tip,
@ -711,7 +728,7 @@ type BlockTxsKey struct {
} }
type BlockTxsValue struct { type BlockTxsValue struct {
TxHashes []*chainhash.Hash `struct-while:"!_eof" json:"tx_hashes"` TxHashes []*chainhash.Hash `struct:"*[32]byte" struct-while:"!_eof" json:"tx_hashes"`
} }
func (k *BlockTxsKey) NewBlockTxsKey(height uint32) *BlockTxsKey { func (k *BlockTxsKey) NewBlockTxsKey(height uint32) *BlockTxsKey {

View file

@ -277,9 +277,9 @@ func MakeHubServer(grp *stop.Group, args *Args) *Server {
// Determine which chain to use based on db and cli values // Determine which chain to use based on db and cli values
dbChain := (*chaincfg.Params)(nil) dbChain := (*chaincfg.Params)(nil)
if myDB != nil && myDB.LastState != nil && myDB.LastState.Genesis != nil { if myDB != nil && myDB.LastState != nil {
// The chain params can be inferred from DBStateValue. // The chain params can be inferred from DBStateValue.
switch *myDB.LastState.Genesis { switch myDB.LastState.Genesis.Hash {
case *chaincfg.MainNetParams.GenesisHash: case *chaincfg.MainNetParams.GenesisHash:
dbChain = &chaincfg.MainNetParams dbChain = &chaincfg.MainNetParams
case *chaincfg.TestNet3Params.GenesisHash: case *chaincfg.TestNet3Params.GenesisHash: