diff --git a/domain/consensus/datastructures/consensusstatestore/consensusstatestore.go b/domain/consensus/datastructures/consensusstatestore/consensusstatestore.go index bb7bb2555..1ab46fbab 100644 --- a/domain/consensus/datastructures/consensusstatestore/consensusstatestore.go +++ b/domain/consensus/datastructures/consensusstatestore/consensusstatestore.go @@ -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") -} diff --git a/domain/consensus/datastructures/consensusstatestore/tips.go b/domain/consensus/datastructures/consensusstatestore/tips.go index a8cb146ce..f9e3a8546 100644 --- a/domain/consensus/datastructures/consensusstatestore/tips.go +++ b/domain/consensus/datastructures/consensusstatestore/tips.go @@ -34,6 +34,5 @@ func (c consensusStateStore) commitTips(dbTx model.DBTransaction) error { return err } - c.stagedTips = nil return nil } diff --git a/domain/consensus/datastructures/consensusstatestore/utxo.go b/domain/consensus/datastructures/consensusstatestore/utxo.go index 2fb8f186b..3b5a2d75a 100644 --- a/domain/consensus/datastructures/consensusstatestore/utxo.go +++ b/domain/consensus/datastructures/consensusstatestore/utxo.go @@ -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 +} diff --git a/domain/consensus/datastructures/consensusstatestore/virtual_diff_parents.go b/domain/consensus/datastructures/consensusstatestore/virtual_diff_parents.go index 93c0ed2ce..bfd61c28a 100644 --- a/domain/consensus/datastructures/consensusstatestore/virtual_diff_parents.go +++ b/domain/consensus/datastructures/consensusstatestore/virtual_diff_parents.go @@ -34,6 +34,5 @@ func (c consensusStateStore) commitVirtualDiffParents(dbTx model.DBTransaction) return err } - c.stagedVirtualDiffParents = nil return nil } diff --git a/domain/consensus/model/interface_datastructures_consensusstatestore.go b/domain/consensus/model/interface_datastructures_consensusstatestore.go index 3b0f2d12d..022f8c547 100644 --- a/domain/consensus/model/interface_datastructures_consensusstatestore.go +++ b/domain/consensus/model/interface_datastructures_consensusstatestore.go @@ -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)