Skip to content

Commit

Permalink
Applied snapshot balances (#1280)
Browse files Browse the repository at this point in the history
* Applied snapshot balances

* Save initial block snapshot.

* MinerPayout diff

* Applied initial snapshot

* Logged snapshots

* Added a parser

* Fixed 0 change case

* supported legacy state hashes

* Logged a height

* Handled failed transaction

* Fixed a mistake of not adding failed changes to snapshot

* Fixed a problem with special asset balance snapshot

* Removed unnecessary comments, stagenet ok

* Fixed linter issues, added validation

* Use 'calculate hashes' flag.

* Move deferred hasher release to its initialization.

* Use 'newestConstInfo' in 'balances.calculateStateHashesAssetBalance'.

* Refactor just issued assets in snapshot generator.

* Refactor 'snapshotGenerator.assetBalanceSnapshotFromBalanceDiff'.

* Refactor 'stateForHashes' methods.

* Removed TODOs, added validation

* Improved validation a bit in 'snapshotGenerator.balanceDiffFromTxDiff'.

* Revert "Save initial block snapshot."

This reverts commit 12b2a6a.

According to the scala node implementation:
- Saved block snapshot must not contain initial block snapshot.
- Light node can calculate all initial data by its own.

---------

Co-authored-by: Nikolay Eskov <[email protected]>
  • Loading branch information
esuwu and nickeskov authored Jan 10, 2024
1 parent 610b2cf commit 7a4fbf8
Show file tree
Hide file tree
Showing 12 changed files with 531 additions and 341 deletions.
61 changes: 0 additions & 61 deletions pkg/proto/snapshot_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,13 @@ type AtomicSnapshot interface {
Apply(SnapshotApplier) error
/* TODO remove it. It is temporarily used to mark snapshots generated by tx diff that shouldn't be applied,
because balances diffs are applied later in the block. */
IsGeneratedByTxDiff() bool
AppendToProtobuf(txSnapshots *g.TransactionStateSnapshot) error
}
type WavesBalanceSnapshot struct {
Address WavesAddress
Balance uint64
}

func (s WavesBalanceSnapshot) IsGeneratedByTxDiff() bool {
return true
}

func (s WavesBalanceSnapshot) Apply(a SnapshotApplier) error { return a.ApplyWavesBalance(s) }

func (s WavesBalanceSnapshot) ToProtobuf() (*g.TransactionStateSnapshot_Balance, error) {
Expand Down Expand Up @@ -70,10 +65,6 @@ type AssetBalanceSnapshot struct {
Balance uint64
}

func (s AssetBalanceSnapshot) IsGeneratedByTxDiff() bool {
return true
}

func (s AssetBalanceSnapshot) Apply(a SnapshotApplier) error { return a.ApplyAssetBalance(s) }

func (s AssetBalanceSnapshot) ToProtobuf() (*g.TransactionStateSnapshot_Balance, error) {
Expand Down Expand Up @@ -119,10 +110,6 @@ type DataEntriesSnapshot struct { // AccountData in pb
DataEntries []DataEntry
}

func (s DataEntriesSnapshot) IsGeneratedByTxDiff() bool {
return false
}

func (s DataEntriesSnapshot) Apply(a SnapshotApplier) error { return a.ApplyDataEntries(s) }

func (s DataEntriesSnapshot) ToProtobuf() (*g.TransactionStateSnapshot_AccountData, error) {
Expand Down Expand Up @@ -169,10 +156,6 @@ type AccountScriptSnapshot struct {
VerifierComplexity uint64
}

func (s AccountScriptSnapshot) IsGeneratedByTxDiff() bool {
return false
}

func (s AccountScriptSnapshot) Apply(a SnapshotApplier) error { return a.ApplyAccountScript(s) }

func (s AccountScriptSnapshot) ToProtobuf() (*g.TransactionStateSnapshot_AccountScript, error) {
Expand Down Expand Up @@ -220,10 +203,6 @@ type AssetScriptSnapshot struct {
Script Script
}

func (s AssetScriptSnapshot) IsGeneratedByTxDiff() bool {
return false
}

func (s AssetScriptSnapshot) Apply(a SnapshotApplier) error { return a.ApplyAssetScript(s) }

func (s AssetScriptSnapshot) ToProtobuf() (*g.TransactionStateSnapshot_AssetScript, error) {
Expand Down Expand Up @@ -266,10 +245,6 @@ type LeaseBalanceSnapshot struct {
LeaseOut uint64
}

func (s LeaseBalanceSnapshot) IsGeneratedByTxDiff() bool {
return true
}

func (s LeaseBalanceSnapshot) Apply(a SnapshotApplier) error { return a.ApplyLeaseBalance(s) }

func (s LeaseBalanceSnapshot) ToProtobuf() (*g.TransactionStateSnapshot_LeaseBalance, error) {
Expand Down Expand Up @@ -330,10 +305,6 @@ type NewLeaseSnapshot struct {
RecipientAddr WavesAddress
}

func (s NewLeaseSnapshot) IsGeneratedByTxDiff() bool {
return false
}

func (s NewLeaseSnapshot) Apply(a SnapshotApplier) error { return a.ApplyNewLease(s) }

func (s NewLeaseSnapshot) ToProtobuf() (*g.TransactionStateSnapshot_NewLease, error) {
Expand Down Expand Up @@ -385,10 +356,6 @@ type CancelledLeaseSnapshot struct {

func (s CancelledLeaseSnapshot) Apply(a SnapshotApplier) error { return a.ApplyCancelledLease(s) }

func (s CancelledLeaseSnapshot) IsGeneratedByTxDiff() bool {
return false
}

func (s CancelledLeaseSnapshot) ToProtobuf() (*g.TransactionStateSnapshot_CancelledLease, error) {
return &g.TransactionStateSnapshot_CancelledLease{
LeaseId: s.LeaseID.Bytes(),
Expand Down Expand Up @@ -419,10 +386,6 @@ type SponsorshipSnapshot struct {
MinSponsoredFee uint64
}

func (s SponsorshipSnapshot) IsGeneratedByTxDiff() bool {
return false
}

func (s SponsorshipSnapshot) Apply(a SnapshotApplier) error { return a.ApplySponsorship(s) }

func (s SponsorshipSnapshot) ToProtobuf() (*g.TransactionStateSnapshot_Sponsorship, error) {
Expand Down Expand Up @@ -461,10 +424,6 @@ type AliasSnapshot struct {
Alias Alias
}

func (s AliasSnapshot) IsGeneratedByTxDiff() bool {
return false
}

func (s AliasSnapshot) Apply(a SnapshotApplier) error { return a.ApplyAlias(s) }

func (s AliasSnapshot) ToProtobuf() (*g.TransactionStateSnapshot_Alias, error) {
Expand Down Expand Up @@ -503,10 +462,6 @@ type FilledVolumeFeeSnapshot struct { // OrderFill
FilledFee uint64
}

func (s FilledVolumeFeeSnapshot) IsGeneratedByTxDiff() bool {
return false
}

func (s FilledVolumeFeeSnapshot) Apply(a SnapshotApplier) error { return a.ApplyFilledVolumeAndFee(s) }

func (s FilledVolumeFeeSnapshot) ToProtobuf() (*g.TransactionStateSnapshot_OrderFill, error) {
Expand Down Expand Up @@ -553,10 +508,6 @@ type NewAssetSnapshot struct {
IsNFT bool
}

func (s NewAssetSnapshot) IsGeneratedByTxDiff() bool {
return false
}

func (s NewAssetSnapshot) Apply(a SnapshotApplier) error { return a.ApplyNewAsset(s) }

func (s NewAssetSnapshot) ToProtobuf() (*g.TransactionStateSnapshot_NewAsset, error) {
Expand Down Expand Up @@ -604,10 +555,6 @@ type AssetVolumeSnapshot struct { // AssetVolume in pb
IsReissuable bool
}

func (s AssetVolumeSnapshot) IsGeneratedByTxDiff() bool {
return false
}

func (s AssetVolumeSnapshot) Apply(a SnapshotApplier) error { return a.ApplyAssetVolume(s) }

func (s AssetVolumeSnapshot) ToProtobuf() (*g.TransactionStateSnapshot_AssetVolume, error) {
Expand Down Expand Up @@ -646,10 +593,6 @@ type AssetDescriptionSnapshot struct { // AssetNameAndDescription in pb
AssetDescription string
}

func (s AssetDescriptionSnapshot) IsGeneratedByTxDiff() bool {
return false
}

func (s AssetDescriptionSnapshot) Apply(a SnapshotApplier) error { return a.ApplyAssetDescription(s) }

func (s AssetDescriptionSnapshot) ToProtobuf() (*g.TransactionStateSnapshot_AssetNameAndDescription, error) {
Expand Down Expand Up @@ -690,10 +633,6 @@ func (s TransactionStatusSnapshot) Apply(a SnapshotApplier) error {
return a.ApplyTransactionsStatus(s)
}

func (s TransactionStatusSnapshot) IsGeneratedByTxDiff() bool {
return false
}

func (s *TransactionStatusSnapshot) FromProtobuf(p g.TransactionStatus) error {
switch p {
case g.TransactionStatus_SUCCEEDED:
Expand Down
63 changes: 29 additions & 34 deletions pkg/state/appender.go
Original file line number Diff line number Diff line change
Expand Up @@ -349,16 +349,22 @@ func (a *txAppender) commitTxApplication(
proto.MustAddressFromPublicKey(a.settings.AddressSchemeCharacter, params.currentMinerPK),
applicationRes.checkerData,
)
diff = applicationRes.changes.diff
applicationStatus = applicationRes.status
)

snapshot, err := a.txHandler.performTx(tx, pi, params.validatingUtx, invocationRes, applicationStatus, diff)
balanceChanges := applicationRes.changes.diff.balancesChanges()
err = a.diffApplier.validateBalancesChanges(balanceChanges)
if err != nil {
return txSnapshot{}, err
}
a.diffStor.reset()
snapshot, err := a.txHandler.performTx(tx, pi, params.validatingUtx, invocationRes, applicationStatus, balanceChanges)
if err != nil {
return txSnapshot{}, wrapErr(TxCommitmentError,
errors.Wrapf(err, "failed to perform transaction %q", base58.Encode(txID)),
)
}

if !params.validatingUtx {
// TODO: snapshots for miner fee should be generated here, but not saved
// They must be saved in snapshot applier
Expand Down Expand Up @@ -591,7 +597,6 @@ func (a *txAppender) appendTx(tx proto.Transaction, params *appendTxParams) (txS
}

// invocationResult may be empty if it was not an Invoke Transaction

snapshot, err := a.commitTxApplication(tx, params, invocationResult, applicationRes)

if err != nil {
Expand All @@ -607,29 +612,6 @@ func (a *txAppender) appendTx(tx proto.Transaction, params *appendTxParams) (txS
return snapshot, nil
}

// rewards and 60% of the fee to the previous miner.
func (a *txAppender) createInitialBlockSnapshot(minerAndRewardDiff txDiff) (txSnapshot, error) {
addrWavesBalanceDiff, _, err := balanceDiffFromTxDiff(minerAndRewardDiff, a.settings.AddressSchemeCharacter)
if err != nil {
return txSnapshot{}, errors.Wrap(err, "failed to create balance diff from tx diff")
}
// add miner address to the diff
var snapshot txSnapshot
for wavesAddress, diffAmount := range addrWavesBalanceDiff {
var fullBalance balanceProfile
fullBalance, err = a.stor.balances.newestWavesBalance(wavesAddress.ID())
if err != nil {
return txSnapshot{}, errors.Wrap(err, "failed to receive sender's waves balance")
}
newBalance := &proto.WavesBalanceSnapshot{
Address: wavesAddress,
Balance: uint64(int64(fullBalance.balance) + diffAmount.balance),
}
snapshot.regular = append(snapshot.regular, newBalance)
}
return snapshot, nil
}

func calculateInitialSnapshotStateHash(
h *txSnapshotHasher,
blockHasParent bool,
Expand Down Expand Up @@ -693,8 +675,9 @@ func (a *txAppender) appendBlock(params *appendBlockParams) error {
if err != nil {
return err
}

// create the initial snapshot
initialSnapshot, err := a.createInitialBlockSnapshot(minerAndRewardDiff)
initialSnapshot, err := a.txHandler.tp.createInitialBlockSnapshot(minerAndRewardDiff.balancesChanges())
if err != nil {
return errors.Wrap(err, "failed to create initial snapshot")
}
Expand All @@ -712,6 +695,21 @@ func (a *txAppender) appendBlock(params *appendBlockParams) error {
}
defer hasher.Release()

// Save miner diff first (for validation)
if err = a.diffStor.saveTxDiff(minerAndRewardDiff); err != nil {
return err
}
err = a.diffApplier.validateBalancesChanges(minerAndRewardDiff.balancesChanges())
if err != nil {
return errors.Wrap(err, "failed to validate miner reward changes")
}
a.diffStor.reset()

err = initialSnapshot.ApplyInitialSnapshot(a.txHandler.sa)
if err != nil {
return errors.Wrap(err, "failed to apply an initial snapshot")
}

// get initial snapshot hash for block
stateHash, err := calculateInitialSnapshotStateHash(
hasher,
Expand All @@ -726,13 +724,6 @@ func (a *txAppender) appendBlock(params *appendBlockParams) error {
)
}

// TODO apply this snapshot when balances are refatored
// err = initialSnapshot.Apply(&snapshotApplier)

// Save miner diff first (for validation)
if err = a.diffStor.saveTxDiff(minerAndRewardDiff); err != nil {
return err
}
blockV5Activated, err := a.stor.features.newestIsActivated(int16(settings.BlockV5))
if err != nil {
return err
Expand Down Expand Up @@ -794,10 +785,14 @@ func (a *txAppender) appendBlock(params *appendBlockParams) error {
if ssErr := a.stor.snapshots.saveSnapshots(params.block.BlockID(), currentBlockHeight, bs); ssErr != nil {
return ssErr
}

// clean up legacy state hash records with zero diffs
a.stor.balances.filterZeroDiffsSHOut(blockID)
// TODO: check snapshot hash with the block snapshot hash if it exists
if shErr := a.stor.stateHashes.saveSnapshotStateHash(stateHash, currentBlockHeight, blockID); shErr != nil {
return errors.Wrapf(shErr, "failed to save block shasnpt hash at height %d", currentBlockHeight)
}

// Save fee distribution of this block.
// This will be needed for createMinerAndRewardDiff() of next block due to NG.
return a.blockDiffer.saveCurFeeDistr(params.block)
Expand Down
10 changes: 5 additions & 5 deletions pkg/state/assets.go
Original file line number Diff line number Diff line change
Expand Up @@ -313,15 +313,16 @@ type assetInfoChange struct {
}

func (a *assets) updateAssetInfo(asset crypto.Digest, ch *assetInfoChange, blockID proto.BlockID) error {
info, err := a.newestChangeableInfo(asset)
assetID := proto.AssetIDFromDigest(asset)
info, err := a.newestChangeableInfo(assetID)
if err != nil {
return errors.Errorf("failed to get asset info: %v\n", err)
}
info.name = ch.newName
info.description = ch.newDescription
info.lastNameDescChangeHeight = ch.newHeight
record := &assetHistoryRecord{assetChangeableInfo: *info}
return a.addNewRecord(proto.AssetIDFromDigest(asset), record, blockID)
return a.addNewRecord(assetID, record, blockID)
}

func (a *assets) newestLastUpdateHeight(assetID proto.AssetID) (uint64, error) {
Expand Down Expand Up @@ -355,8 +356,7 @@ func (a *assets) newestConstInfo(assetID proto.AssetID) (*assetConstInfo, error)
return a.constInfo(assetID)
}

func (a *assets) newestChangeableInfo(asset crypto.Digest) (*assetChangeableInfo, error) {
assetID := proto.AssetIDFromDigest(asset)
func (a *assets) newestChangeableInfo(assetID proto.AssetID) (*assetChangeableInfo, error) {
if info, ok := a.uncertainAssetInfo[assetID]; ok {
return &info.assetInfo.assetChangeableInfo, nil
}
Expand Down Expand Up @@ -391,7 +391,7 @@ func (a *assets) newestAssetInfo(assetID proto.AssetID) (*assetInfo, error) {
if err != nil {
return nil, err
}
changeableInfo, err := a.newestChangeableInfo(proto.ReconstructDigest(assetID, constInfo.tail))
changeableInfo, err := a.newestChangeableInfo(assetID)
if err != nil {
return nil, err
}
Expand Down
Loading

0 comments on commit 7a4fbf8

Please sign in to comment.