[NOD-1509] Implement StageVirtualUTXOSet (#999)

* [NOD-1509] Implement StageVirtualUTXODiff

* [NOD-1509] Fix HasUTXOByOutpoint, get rid of database.ErrNotFound, and fix errors
This commit is contained in:
Ori Newman 2020-11-04 06:30:08 -08:00 committed by GitHub
parent ce95c6dc9d
commit 2eb0d946e5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 103 additions and 16 deletions

View File

@ -10,6 +10,7 @@ type consensusStateStore struct {
stagedTips []*externalapi.DomainHash
stagedVirtualDiffParents []*externalapi.DomainHash
stagedVirtualUTXODiff *model.UTXODiff
stagedVirtualUTXOSet model.UTXOCollection
}
// New instantiates a new ConsensusStateStore
@ -21,6 +22,7 @@ func (c consensusStateStore) Discard() {
c.stagedTips = nil
c.stagedVirtualUTXODiff = nil
c.stagedVirtualDiffParents = nil
c.stagedVirtualUTXOSet = nil
}
func (c consensusStateStore) Commit(dbTx model.DBTransaction) error {
@ -32,11 +34,19 @@ func (c consensusStateStore) Commit(dbTx model.DBTransaction) error {
if err != nil {
return err
}
err = c.commitVirtualUTXODiff(dbTx)
if err != nil {
return err
}
err = c.commitVirtualUTXOSet(dbTx)
if err != nil {
return err
}
c.Discard()
return nil
}
@ -45,7 +55,3 @@ func (c consensusStateStore) IsStaged() bool {
c.stagedVirtualDiffParents != nil ||
c.stagedVirtualUTXODiff != nil
}
func (c consensusStateStore) StageVirtualUTXOSet(virtualUTXOSetIterator model.ReadOnlyUTXOSetIterator) {
panic("implement me")
}

View File

@ -34,6 +34,5 @@ func (c consensusStateStore) commitTips(dbTx model.DBTransaction) error {
return err
}
c.stagedTips = nil
return nil
}

View File

@ -4,7 +4,7 @@ import (
"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/infrastructure/db/database"
"github.com/pkg/errors"
)
var utxoSetBucket = dbkeys.MakeBucket([]byte("virtual-utxo-set"))
@ -18,11 +18,20 @@ func utxoKey(outpoint *externalapi.DomainOutpoint) (model.DBKey, error) {
return utxoSetBucket.Key(serializedOutpoint), nil
}
func (c consensusStateStore) StageVirtualUTXODiff(virtualUTXODiff *model.UTXODiff) {
func (c consensusStateStore) StageVirtualUTXODiff(virtualUTXODiff *model.UTXODiff) error {
if c.stagedVirtualUTXOSet != nil {
return errors.New("cannot stage virtual UTXO diff while virtual UTXO set is staged")
}
c.stagedVirtualUTXODiff = virtualUTXODiff
return nil
}
func (c consensusStateStore) commitVirtualUTXODiff(dbTx model.DBTransaction) error {
if c.stagedVirtualUTXOSet != nil {
return errors.New("cannot commit virtual UTXO diff while virtual UTXO set is staged")
}
for toRemoveOutpoint := range c.stagedVirtualUTXODiff.ToRemove {
dbKey, err := utxoKey(&toRemoveOutpoint)
if err != nil {
@ -49,7 +58,28 @@ func (c consensusStateStore) commitVirtualUTXODiff(dbTx model.DBTransaction) err
}
}
c.stagedVirtualUTXODiff = nil
return nil
}
func (c consensusStateStore) commitVirtualUTXOSet(dbTx model.DBTransaction) error {
if c.stagedVirtualUTXODiff != nil {
return errors.New("cannot commit virtual UTXO set while virtual UTXO diff is staged")
}
for outpoint, utxoEntry := range c.stagedVirtualUTXOSet {
dbKey, err := utxoKey(&outpoint)
if err != nil {
return err
}
serializedEntry, err := serializeUTXOEntry(utxoEntry)
if err != nil {
return err
}
err = dbTx.Put(dbKey, serializedEntry)
if err != nil {
return err
}
}
return nil
}
@ -57,11 +87,24 @@ func (c consensusStateStore) commitVirtualUTXODiff(dbTx model.DBTransaction) err
func (c consensusStateStore) UTXOByOutpoint(dbContext model.DBReader, outpoint *externalapi.DomainOutpoint) (
*externalapi.UTXOEntry, error) {
if _, ok := c.stagedVirtualUTXODiff.ToRemove[*outpoint]; ok {
return nil, database.ErrNotFound
if c.stagedVirtualUTXOSet != nil {
return c.utxoByOutpointFromStagedVirtualUTXOSet(outpoint)
}
if utxoEntry, ok := c.stagedVirtualUTXODiff.ToAdd[*outpoint]; ok {
return utxoEntry, nil
return c.utxoByOutpointFromStagedVirtualUTXODiff(dbContext, outpoint)
}
func (c consensusStateStore) utxoByOutpointFromStagedVirtualUTXODiff(dbContext model.DBReader,
outpoint *externalapi.DomainOutpoint) (
*externalapi.UTXOEntry, error) {
if c.stagedVirtualUTXODiff != nil {
if _, ok := c.stagedVirtualUTXODiff.ToRemove[*outpoint]; ok {
return nil, errors.Errorf("outpoint was not found")
}
if utxoEntry, ok := c.stagedVirtualUTXODiff.ToAdd[*outpoint]; ok {
return utxoEntry, nil
}
}
key, err := utxoKey(outpoint)
@ -77,9 +120,27 @@ func (c consensusStateStore) UTXOByOutpoint(dbContext model.DBReader, outpoint *
return deserializeUTXOEntry(serializedUTXOEntry)
}
func (c consensusStateStore) utxoByOutpointFromStagedVirtualUTXOSet(outpoint *externalapi.DomainOutpoint) (
*externalapi.UTXOEntry, error) {
if utxoEntry, ok := c.stagedVirtualUTXOSet[*outpoint]; ok {
return utxoEntry, nil
}
return nil, errors.Errorf("outpoint was not found")
}
func (c consensusStateStore) HasUTXOByOutpoint(dbContext model.DBReader, outpoint *externalapi.DomainOutpoint) (bool, error) {
if c.stagedVirtualUTXOSet != nil {
return c.hasUTXOByOutpointFromStagedVirtualUTXOSet(outpoint), nil
}
return c.hasUTXOByOutpointFromStagedVirtualUTXODiff(dbContext, outpoint)
}
func (c consensusStateStore) hasUTXOByOutpointFromStagedVirtualUTXODiff(dbContext model.DBReader,
outpoint *externalapi.DomainOutpoint) (bool, error) {
if _, ok := c.stagedVirtualUTXODiff.ToRemove[*outpoint]; ok {
return false, database.ErrNotFound
return false, nil
}
if _, ok := c.stagedVirtualUTXODiff.ToAdd[*outpoint]; ok {
return true, nil
@ -93,6 +154,11 @@ func (c consensusStateStore) HasUTXOByOutpoint(dbContext model.DBReader, outpoin
return dbContext.Has(key)
}
func (c consensusStateStore) hasUTXOByOutpointFromStagedVirtualUTXOSet(outpoint *externalapi.DomainOutpoint) bool {
_, ok := c.stagedVirtualUTXOSet[*outpoint]
return ok
}
func (c consensusStateStore) VirtualUTXOSetIterator(dbContext model.DBReader) (model.ReadOnlyUTXOSetIterator, error) {
cursor, err := dbContext.Cursor(utxoSetBucket)
if err != nil {
@ -137,3 +203,20 @@ func (u utxoSetIterator) Get() (outpoint *externalapi.DomainOutpoint, utxoEntry
return outpoint, utxoEntry
}
func (c consensusStateStore) StageVirtualUTXOSet(virtualUTXOSetIterator model.ReadOnlyUTXOSetIterator) error {
if c.stagedVirtualUTXODiff != nil {
return errors.New("cannot stage virtual UTXO set while virtual UTXO diff is staged")
}
c.stagedVirtualUTXOSet = make(model.UTXOCollection)
for virtualUTXOSetIterator.Next() {
outpoint, entry := virtualUTXOSetIterator.Get()
if _, exists := c.stagedVirtualUTXOSet[*outpoint]; exists {
return errors.Errorf("outpoint %s is found more than once in the given iterator", outpoint)
}
c.stagedVirtualUTXOSet[*outpoint] = entry
}
return nil
}

View File

@ -34,6 +34,5 @@ func (c consensusStateStore) commitVirtualDiffParents(dbTx model.DBTransaction)
return err
}
c.stagedVirtualDiffParents = nil
return nil
}

View File

@ -7,8 +7,8 @@ type ConsensusStateStore interface {
Store
IsStaged() bool
StageVirtualUTXODiff(virtualUTXODiff *UTXODiff)
StageVirtualUTXOSet(virtualUTXOSetIterator ReadOnlyUTXOSetIterator)
StageVirtualUTXODiff(virtualUTXODiff *UTXODiff) error
StageVirtualUTXOSet(virtualUTXOSetIterator ReadOnlyUTXOSetIterator) error
UTXOByOutpoint(dbContext DBReader, outpoint *externalapi.DomainOutpoint) (*externalapi.UTXOEntry, error)
HasUTXOByOutpoint(dbContext DBReader, outpoint *externalapi.DomainOutpoint) (bool, error)
VirtualUTXOSetIterator(dbContext DBReader) (ReadOnlyUTXOSetIterator, error)