mirror of
https://github.com/kaspanet/kaspad.git
synced 2025-05-19 13:26:47 +00:00

* Use selectedParent instead of selectedTip for non-selectedTip blocks in restoreSingleBlockStatus * Cache the selectedParent for re-use in a resolveSingleBlockStatus chain * Implement and use reverseUTXOSet * Reverse blocks in correct order * Support resolveBlockStatus without separate stagingAreas for usage of testConsensus * Handle the case where the tip of the resolved block is not the next selectedTip * Unify isResolveTip * Some minor fixes and cleanup * Add full finality window re-org test to stability-slow * rename: useSeparateStagingAreasPerBlock -> useSeparateStagingAreaPerBlock * Better logs in resolveSingleBlockStatus * A few retouches to reverseUTXODiffs * TEMPORARY COMMIT: EXTRAT ALL DIFFFROMS TO SEPARATE METHODS * TEMPORARY COMMIT: REMOVE DIFFICULTY CHECKS IN DEVNET * Don't pre-allocate in utxo-algebra, since the numbers are not known ahead-of-time * Add some logs to reverseUTXODiffs * Revert "TEMPORARY COMMIT: REMOVE DIFFICULTY CHECKS IN DEVNET" This reverts commit c0af9dc6ade78a914c970e11bc63c34605565f57. * Revert "TEMPORARY COMMIT: EXTRAT ALL DIFFFROMS TO SEPARATE METHODS" This reverts commit 4fcca1b48c3a1183598833a355b9bfaf169edba1. * Remove redundant paranthesis * Revise some logs messages * Rename:oneBlockBeforeCurrentUTXOSet -> lastResolvedBlockUTXOSet * Don't break if the block was resolved as invalid * rename unverifiedBlocks to recentlyVerifiedBlcks in reverseUTXODiffs * Add errors.New to the panic, for a stack trace * Reverse the UTXODiffs after the main block has been commited * Use the correct value for previousUTXODiff * Add test for ReverseUTXODiff * Fix some names and comments * Update TestReverseUTXODiffs to use consensus.Config * Fix comments mentioning 'oneBlockBeforeTip'
168 lines
4.3 KiB
Go
168 lines
4.3 KiB
Go
package utxo
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
|
"github.com/kaspanet/kaspad/domain/consensus/utils/consensushashing"
|
|
"github.com/kaspanet/kaspad/domain/consensus/utils/transactionhelper"
|
|
"github.com/pkg/errors"
|
|
)
|
|
|
|
type mutableUTXODiff struct {
|
|
toAdd utxoCollection
|
|
toRemove utxoCollection
|
|
|
|
immutableReferences []*immutableUTXODiff
|
|
}
|
|
|
|
// NewMutableUTXODiff creates an empty mutable UTXO-Diff
|
|
func NewMutableUTXODiff() externalapi.MutableUTXODiff {
|
|
return newMutableUTXODiff()
|
|
}
|
|
|
|
func newMutableUTXODiff() *mutableUTXODiff {
|
|
return &mutableUTXODiff{
|
|
toAdd: utxoCollection{},
|
|
toRemove: utxoCollection{},
|
|
}
|
|
}
|
|
|
|
func (mud *mutableUTXODiff) ToImmutable() externalapi.UTXODiff {
|
|
immutableReference := &immutableUTXODiff{
|
|
mutableUTXODiff: mud,
|
|
isInvalidated: false,
|
|
}
|
|
|
|
mud.immutableReferences = append(mud.immutableReferences, immutableReference)
|
|
|
|
return immutableReference
|
|
}
|
|
|
|
func (mud *mutableUTXODiff) invalidateImmutableReferences() {
|
|
for _, immutableReference := range mud.immutableReferences {
|
|
immutableReference.isInvalidated = true
|
|
}
|
|
|
|
mud.immutableReferences = nil
|
|
}
|
|
|
|
func (mud *mutableUTXODiff) WithDiff(other externalapi.UTXODiff) (externalapi.UTXODiff, error) {
|
|
o, ok := other.(*immutableUTXODiff)
|
|
if !ok {
|
|
return nil, errors.New("other is not of type *immutableUTXODiff")
|
|
}
|
|
|
|
result, err := withDiff(mud, o.mutableUTXODiff)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return result.ToImmutable(), nil
|
|
}
|
|
|
|
func (mud *mutableUTXODiff) WithDiffInPlace(other externalapi.UTXODiff) error {
|
|
o, ok := other.(*immutableUTXODiff)
|
|
if !ok {
|
|
return errors.New("other is not of type *immutableUTXODiff")
|
|
}
|
|
|
|
mud.invalidateImmutableReferences()
|
|
|
|
return withDiffInPlace(mud, o.mutableUTXODiff)
|
|
}
|
|
|
|
func (mud *mutableUTXODiff) DiffFrom(other externalapi.UTXODiff) (externalapi.UTXODiff, error) {
|
|
o, ok := other.(*immutableUTXODiff)
|
|
if !ok {
|
|
return nil, errors.New("other is not of type *immutableUTXODiff")
|
|
}
|
|
|
|
result, err := diffFrom(mud, o.mutableUTXODiff)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return result.ToImmutable(), nil
|
|
}
|
|
|
|
func (mud *mutableUTXODiff) ToAdd() externalapi.UTXOCollection {
|
|
return mud.toAdd
|
|
}
|
|
|
|
func (mud *mutableUTXODiff) ToRemove() externalapi.UTXOCollection {
|
|
return mud.toRemove
|
|
}
|
|
func (mud *mutableUTXODiff) AddTransaction(transaction *externalapi.DomainTransaction, blockDAAScore uint64) error {
|
|
mud.invalidateImmutableReferences()
|
|
|
|
for _, input := range transaction.Inputs {
|
|
err := mud.removeEntry(&input.PreviousOutpoint, input.UTXOEntry)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
isCoinbase := transactionhelper.IsCoinBase(transaction)
|
|
transactionID := *consensushashing.TransactionID(transaction)
|
|
for i, output := range transaction.Outputs {
|
|
outpoint := &externalapi.DomainOutpoint{
|
|
TransactionID: transactionID,
|
|
Index: uint32(i),
|
|
}
|
|
entry := NewUTXOEntry(output.Value, output.ScriptPublicKey, isCoinbase, blockDAAScore)
|
|
|
|
err := mud.addEntry(outpoint, entry)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (mud *mutableUTXODiff) addEntry(outpoint *externalapi.DomainOutpoint, entry externalapi.UTXOEntry) error {
|
|
if mud.toRemove.containsWithDAAScore(outpoint, entry.BlockDAAScore()) {
|
|
mud.toRemove.remove(outpoint)
|
|
} else if mud.toAdd.Contains(outpoint) {
|
|
return errors.Errorf("AddEntry: Cannot add outpoint %s twice", outpoint)
|
|
} else {
|
|
mud.toAdd.add(outpoint, entry)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (mud *mutableUTXODiff) removeEntry(outpoint *externalapi.DomainOutpoint, entry externalapi.UTXOEntry) error {
|
|
if mud.toAdd.containsWithDAAScore(outpoint, entry.BlockDAAScore()) {
|
|
mud.toAdd.remove(outpoint)
|
|
} else if mud.toRemove.Contains(outpoint) {
|
|
return errors.Errorf("removeEntry: Cannot remove outpoint %s twice", outpoint)
|
|
} else {
|
|
mud.toRemove.add(outpoint, entry)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (mud *mutableUTXODiff) clone() *mutableUTXODiff {
|
|
if mud == nil {
|
|
return nil
|
|
}
|
|
|
|
return &mutableUTXODiff{
|
|
toAdd: mud.toAdd.Clone(),
|
|
toRemove: mud.toRemove.Clone(),
|
|
}
|
|
}
|
|
|
|
func (mud *mutableUTXODiff) String() string {
|
|
return fmt.Sprintf("toAdd: %s; toRemove: %s", mud.toAdd, mud.toRemove)
|
|
}
|
|
|
|
func (mud *mutableUTXODiff) Reversed() *mutableUTXODiff {
|
|
return &mutableUTXODiff{
|
|
toAdd: mud.toRemove,
|
|
toRemove: mud.toAdd,
|
|
immutableReferences: mud.immutableReferences,
|
|
}
|
|
}
|