Ori Newman 2abd4a274b
[NOD-1496] Implement headers only verification (#987)
* [NOD-1496] Implement headers only verification

* [NOD-1496] Add checkParentsExist

* [NOD-1496] Stage block statuses in block processor

* [NOD-1496] Rename AddBlock->AddHeaderTip

* [NOD-1496] Return early from validateAndInsertBlock on header only and put ValidateProofOfWorkAndDifficulty inside validateBlock
2020-11-02 16:30:59 +02:00

121 lines
3.5 KiB
Go

package pruningstore
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"
)
var pruningBlockHashKey = dbkeys.MakeBucket().Key([]byte("pruning-block-hash"))
var pruningSerializedUTXOSetkey = dbkeys.MakeBucket().Key([]byte("pruning-utxo-set"))
// pruningStore represents a store for the current pruning state
type pruningStore struct {
pruningPointStaging *externalapi.DomainHash
serializedUTXOSetStaging []byte
}
// New instantiates a new PruningStore
func New() model.PruningStore {
return &pruningStore{
pruningPointStaging: nil,
serializedUTXOSetStaging: nil,
}
}
// Stage stages the pruning state
func (ps *pruningStore) Stage(pruningPointBlockHash *externalapi.DomainHash, pruningPointUTXOSetBytes []byte) {
ps.pruningPointStaging = pruningPointBlockHash
ps.serializedUTXOSetStaging = pruningPointUTXOSetBytes
}
func (ps *pruningStore) IsStaged() bool {
return ps.pruningPointStaging != nil || ps.serializedUTXOSetStaging != nil
}
func (ps *pruningStore) Discard() {
ps.pruningPointStaging = nil
ps.serializedUTXOSetStaging = nil
}
func (ps *pruningStore) Commit(dbTx model.DBTransaction) error {
pruningPointBytes, err := ps.serializePruningPoint(ps.pruningPointStaging)
if err != nil {
return err
}
err = dbTx.Put(pruningBlockHashKey, pruningPointBytes)
if err != nil {
return err
}
utxoSetBytes, err := ps.serializeUTXOSetBytes(ps.serializedUTXOSetStaging)
if err != nil {
return err
}
err = dbTx.Put(pruningSerializedUTXOSetkey, utxoSetBytes)
if err != nil {
return err
}
ps.Discard()
return nil
}
// PruningPoint gets the current pruning point
func (ps *pruningStore) PruningPoint(dbContext model.DBReader) (*externalapi.DomainHash, error) {
if ps.pruningPointStaging != nil {
return ps.pruningPointStaging, nil
}
blockHashBytes, err := dbContext.Get(pruningBlockHashKey)
if err != nil {
return nil, err
}
blockHash, err := ps.deserializePruningPoint(blockHashBytes)
if err != nil {
return nil, err
}
return blockHash, nil
}
// PruningPointSerializedUTXOSet returns the serialized UTXO set of the current pruning point
func (ps *pruningStore) PruningPointSerializedUTXOSet(dbContext model.DBReader) ([]byte, error) {
if ps.serializedUTXOSetStaging != nil {
return ps.serializedUTXOSetStaging, nil
}
return dbContext.Get(pruningSerializedUTXOSetkey)
}
func (ps *pruningStore) serializePruningPoint(pruningPoint *externalapi.DomainHash) ([]byte, error) {
return proto.Marshal(serialization.DomainHashToDbHash(pruningPoint))
}
func (ps *pruningStore) deserializePruningPoint(pruningPointBytes []byte) (*externalapi.DomainHash, error) {
dbHash := &serialization.DbHash{}
err := proto.Unmarshal(pruningPointBytes, dbHash)
if err != nil {
return nil, err
}
return serialization.DbHashToDomainHash(dbHash)
}
func (ps *pruningStore) serializeUTXOSetBytes(pruningPointUTXOSetBytes []byte) ([]byte, error) {
return proto.Marshal(&serialization.DbPruningPointUTXOSetBytes{Bytes: pruningPointUTXOSetBytes})
}
func (ps *pruningStore) deserializeUTXOSetBytes(dbPruningPointUTXOSetBytes []byte) ([]byte, error) {
dbPruningPointUTXOSet := &serialization.DbPruningPointUTXOSetBytes{}
err := proto.Unmarshal(dbPruningPointUTXOSetBytes, dbPruningPointUTXOSet)
if err != nil {
return nil, err
}
return dbPruningPointUTXOSet.Bytes, nil
}