mirror of
https://github.com/kaspanet/kaspad.git
synced 2025-05-24 15:56:42 +00:00

* [NOD-1493] Add DbAcceptanceData. * [NOD-1493] Add DbBlockRelations. * [NOD-1493] Add DbBlockStatus. * [NOD-1493] Add DbBlockGhostdagData. * [NOD-1493] Add DbMultiset. * [NOD-1493] Add DbPruningPoint. * [NOD-1493] Add DbUtxoSet. * [NOD-1493] Add DbReachabilityData. * [NOD-1493] Add DbReachabilityReindexRoot. * [NOD-1493] Add DbUtxoDiff. * [NOD-1493] Add DbUtxoDiffChild. * [NOD-1493] Make sure everything is lowercase. * [NOD-1493] Add DbHash. * [NOD-1493] Fix BlockHeaderStore.
167 lines
5.2 KiB
Go
167 lines
5.2 KiB
Go
package blockheaderstore
|
|
|
|
import (
|
|
"github.com/golang/protobuf/proto"
|
|
"github.com/kaspanet/kaspad/domain/consensus/database/serialization"
|
|
"github.com/kaspanet/kaspad/domain/consensus/model"
|
|
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
|
"github.com/kaspanet/kaspad/domain/consensus/utils/dbkeys"
|
|
"github.com/kaspanet/kaspad/domain/consensus/utils/hashes"
|
|
)
|
|
|
|
var bucket = dbkeys.MakeBucket([]byte("block-headers"))
|
|
|
|
// blockHeaderStore represents a store of blocks
|
|
type blockHeaderStore struct {
|
|
staging map[externalapi.DomainHash]*externalapi.DomainBlockHeader
|
|
}
|
|
|
|
// New instantiates a new BlockHeaderStore
|
|
func New() model.BlockHeaderStore {
|
|
return &blockHeaderStore{
|
|
staging: make(map[externalapi.DomainHash]*externalapi.DomainBlockHeader),
|
|
}
|
|
}
|
|
|
|
// Stage stages the given block header for the given blockHash
|
|
func (bms *blockHeaderStore) Stage(blockHash *externalapi.DomainHash, blockHeader *externalapi.DomainBlockHeader) {
|
|
bms.staging[*blockHash] = blockHeader
|
|
}
|
|
|
|
func (bms *blockHeaderStore) IsStaged() bool {
|
|
return len(bms.staging) != 0
|
|
}
|
|
|
|
func (bms *blockHeaderStore) Discard() {
|
|
bms.staging = make(map[externalapi.DomainHash]*externalapi.DomainBlockHeader)
|
|
}
|
|
|
|
func (bms *blockHeaderStore) Commit(dbTx model.DBTransaction) error {
|
|
for hash, header := range bms.staging {
|
|
headerBytes, err := bms.serializeHeader(header)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
err = dbTx.Put(bms.hashAsKey(&hash), headerBytes)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
bms.Discard()
|
|
return nil
|
|
}
|
|
|
|
// BlockHeader gets the block header associated with the given blockHash
|
|
func (bms *blockHeaderStore) BlockHeader(dbContext model.DBReader, blockHash *externalapi.DomainHash) (*externalapi.DomainBlockHeader, error) {
|
|
if header, ok := bms.staging[*blockHash]; ok {
|
|
return header, nil
|
|
}
|
|
|
|
headerBytes, err := dbContext.Get(bms.hashAsKey(blockHash))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return bms.deserializeHeader(headerBytes)
|
|
}
|
|
|
|
// HasBlock returns whether a block header with a given hash exists in the store.
|
|
func (bms *blockHeaderStore) HasBlockHeader(dbContext model.DBReader, blockHash *externalapi.DomainHash) (bool, error) {
|
|
if _, ok := bms.staging[*blockHash]; ok {
|
|
return true, nil
|
|
}
|
|
|
|
exists, err := dbContext.Has(bms.hashAsKey(blockHash))
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
|
|
return exists, nil
|
|
}
|
|
|
|
// BlockHeaders gets the block headers associated with the given blockHashes
|
|
func (bms *blockHeaderStore) BlockHeaders(dbContext model.DBReader, blockHashes []*externalapi.DomainHash) ([]*externalapi.DomainBlockHeader, error) {
|
|
headers := make([]*externalapi.DomainBlockHeader, len(blockHashes))
|
|
for i, hash := range blockHashes {
|
|
var err error
|
|
headers[i], err = bms.BlockHeader(dbContext, hash)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
return headers, nil
|
|
}
|
|
|
|
// Delete deletes the block associated with the given blockHash
|
|
func (bms *blockHeaderStore) Delete(dbTx model.DBTransaction, blockHash *externalapi.DomainHash) error {
|
|
if _, ok := bms.staging[*blockHash]; ok {
|
|
delete(bms.staging, *blockHash)
|
|
return nil
|
|
}
|
|
return dbTx.Delete(bms.hashAsKey(blockHash))
|
|
}
|
|
|
|
func (bms *blockHeaderStore) hashAsKey(hash *externalapi.DomainHash) model.DBKey {
|
|
return bucket.Key(hash[:])
|
|
}
|
|
|
|
func (bms *blockHeaderStore) serializeHeader(header *externalapi.DomainBlockHeader) ([]byte, error) {
|
|
dbParentHashes := make([]*serialization.DbHash, len(header.ParentHashes))
|
|
for i, parentHash := range header.ParentHashes {
|
|
dbParentHashes[i] = &serialization.DbHash{Hash: parentHash[:]}
|
|
}
|
|
|
|
dbBlockHeader := &serialization.DbBlockHeader{
|
|
Version: header.Version,
|
|
ParentHashes: dbParentHashes,
|
|
HashMerkleRoot: &serialization.DbHash{Hash: header.HashMerkleRoot[:]},
|
|
AcceptedIDMerkleRoot: &serialization.DbHash{Hash: header.AcceptedIDMerkleRoot[:]},
|
|
UtxoCommitment: &serialization.DbHash{Hash: header.UTXOCommitment[:]},
|
|
TimeInMilliseconds: header.TimeInMilliseconds,
|
|
Bits: header.Bits,
|
|
Nonce: header.Nonce,
|
|
}
|
|
|
|
return proto.Marshal(dbBlockHeader)
|
|
}
|
|
|
|
func (bms *blockHeaderStore) deserializeHeader(headerBytes []byte) (*externalapi.DomainBlockHeader, error) {
|
|
dbBlockHeader := &serialization.DbBlockHeader{}
|
|
err := proto.Unmarshal(headerBytes, dbBlockHeader)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
parentHashes := make([]*externalapi.DomainHash, len(dbBlockHeader.ParentHashes))
|
|
for i, dbParentHash := range dbBlockHeader.ParentHashes {
|
|
parentHashes[i], err = hashes.FromBytes(dbParentHash.Hash)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
hashMerkleRoot, err := hashes.FromBytes(dbBlockHeader.HashMerkleRoot.Hash)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
acceptedIDMerkleRoot, err := hashes.FromBytes(dbBlockHeader.AcceptedIDMerkleRoot.Hash)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
utxoCommitment, err := hashes.FromBytes(dbBlockHeader.UtxoCommitment.Hash)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return &externalapi.DomainBlockHeader{
|
|
Version: dbBlockHeader.Version,
|
|
ParentHashes: parentHashes,
|
|
HashMerkleRoot: *hashMerkleRoot,
|
|
AcceptedIDMerkleRoot: *acceptedIDMerkleRoot,
|
|
UTXOCommitment: *utxoCommitment,
|
|
TimeInMilliseconds: dbBlockHeader.TimeInMilliseconds,
|
|
Bits: dbBlockHeader.Bits,
|
|
Nonce: dbBlockHeader.Nonce,
|
|
}, nil
|
|
}
|