-
Notifications
You must be signed in to change notification settings - Fork 37
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Node transaction snapshots #1078
Merged
esuwu
merged 49 commits into
node-transactions-snapshots-types
from
node-transaction-snapshots
Jun 30, 2023
Merged
Changes from 40 commits
Commits
Show all changes
49 commits
Select commit
Hold shift + click to select a range
a20285a
Added a conversion function
esuwu f19b9a4
Merge branch 'node-transactions-snapshots-types' into node-transactio…
esuwu fe5e2eb
Added payment transaction conversion
esuwu 5f9ffef
Merge branch 'node-transactions-snapshots-types' into node-transactio…
esuwu a80fb2b
Added transfer tx conversion
esuwu 516a1c7
Merge branch 'node-transactions-snapshots-types' into node-transactio…
esuwu ef5c2f7
Transfer tx conversion changed
esuwu 1d20048
Added issue and reissue tx conversions
esuwu 30f6ce2
Merge branch 'node-transactions-snapshots-types' into node-transactio…
esuwu 39fb959
Issue
esuwu fb8f27f
Merge branch 'node-transactions-snapshots-types' into node-transactio…
esuwu db76e0d
Merge branch 'node-transactions-snapshots-types' into node-transactio…
esuwu a8a6670
Merge branch 'node-transactions-snapshots-types' into node-transactio…
esuwu b570eb7
Merge branch 'node-transactions-snapshots-types' into node-transactio…
esuwu ce7a0fc
Merge branch 'node-transactions-snapshots-types' into node-transactio…
esuwu 048e04b
Merge branch 'node-transactions-snapshots-types' into node-transactio…
esuwu de38edc
Issue, reissue, burn, exchange
esuwu 17a6687
Merge branch 'node-transactions-snapshots-types' into node-transactio…
esuwu 8e470a8
Merge branch 'node-transactions-snapshots-types' into node-transactio…
esuwu f416ea0
Merge branch 'node-transactions-snapshots-types' into node-transactio…
esuwu 1ddae7a
Hanled lease transactions
esuwu 147c280
Merge branch 'node-transactions-snapshots-types' into node-transactio…
esuwu e67edea
Finished performers
esuwu a590cbb
Added snapshots for all types of transactions
esuwu 5b13025
Merge branch 'master' into node-transactions-snapshots-types
esuwu 6c5b791
Merged from master
esuwu dc87a94
Merge branch 'node-transactions-snapshots-types' into node-transactio…
esuwu 42f26e6
Fixed types after merging
esuwu 7b8438e
Fixed issue snapshot mistake
esuwu 8c4a181
Added rewards snapshot in append block
esuwu a01a14d
Merge branch 'node-transactions-snapshots-types' into node-transactio…
esuwu d7d8585
Changed functions to newest
esuwu e3be090
Merge branch 'node-transactions-snapshots-types' into node-transactio…
esuwu b783632
Added snapshots from actions
esuwu 9665d45
Removed todos
esuwu 62fbfaf
Deleted useless code
esuwu ba90197
Fixed a mistake with leasing cancel
esuwu a19d710
Added tests for issue and reissue transactions
esuwu ddbaa2f
Fixed tests
esuwu e1c48c3
Merge branch 'node-transactions-snapshots-types' into node-transactio…
esuwu d28da6a
fixed implicit memory aliasing
esuwu 8843880
Added tests for burn, lease, lease cancel, exchange and create alias …
esuwu 8cd823f
Added tests for data, sponsorship, set account and asset script trans…
esuwu cfef63a
Added a test for the invoke transaction snapshots
esuwu 5458c20
Merge branch 'node-transactions-snapshots-types' into node-transactio…
esuwu 624df00
Fixed after merge
esuwu 1f45400
Fixed a function
esuwu 885f421
Merged from snapshots types
esuwu 256dc87
Moved snapshot generation
esuwu File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -319,49 +319,55 @@ func (a *txAppender) saveTransactionIdByAddresses(addresses []proto.WavesAddress | |
return nil | ||
} | ||
|
||
func (a *txAppender) commitTxApplication(tx proto.Transaction, params *appendTxParams, res *applicationResult) error { | ||
func (a *txAppender) commitTxApplication(tx proto.Transaction, params *appendTxParams, invocationRes *invocationResult, applicationRes *applicationResult) (TransactionSnapshot, error) { | ||
// Add transaction ID to recent IDs. | ||
txID, err := tx.GetID(a.settings.AddressSchemeCharacter) | ||
if err != nil { | ||
return wrapErr(TxCommitmentError, errors.Errorf("failed to get tx id: %v", err)) | ||
return nil, wrapErr(TxCommitmentError, errors.Errorf("failed to get tx id: %v", err)) | ||
} | ||
a.recentTxIds[string(txID)] = empty | ||
// Update script runs. | ||
a.totalScriptsRuns += res.totalScriptsRuns | ||
a.totalScriptsRuns += applicationRes.totalScriptsRuns | ||
// Update complexity. | ||
a.sc.addRecentTxComplexity() | ||
// Save balance diff. | ||
if err := a.diffStor.saveTxDiff(res.changes.diff); err != nil { | ||
return wrapErr(TxCommitmentError, errors.Errorf("failed to save balance diff: %v", err)) | ||
// TODO get balances snapshots | ||
if err := a.diffStor.saveTxDiff(applicationRes.changes.diff); err != nil { | ||
return nil, wrapErr(TxCommitmentError, errors.Errorf("failed to save balance diff: %v", err)) | ||
} | ||
// Perform state changes. | ||
if res.status { | ||
currentMinerAddress := proto.MustAddressFromPublicKey(a.settings.AddressSchemeCharacter, params.currentMinerPK) | ||
|
||
var snapshot TransactionSnapshot | ||
if applicationRes.status { | ||
// We only perform tx in case it has not failed. | ||
performerInfo := &performerInfo{ | ||
height: params.checkerInfo.height, | ||
stateActionsCounter: params.stateActionsCounterInBlock, | ||
blockID: params.checkerInfo.blockID, | ||
currentMinerAddress: currentMinerAddress, | ||
stateActionsCounter: params.stateActionsCounterInBlock, | ||
} | ||
if err := a.txHandler.performTx(tx, performerInfo); err != nil { | ||
return wrapErr(TxCommitmentError, errors.Errorf("failed to perform: %v", err)) | ||
// TODO other snapshots | ||
snapshot, err = a.txHandler.performTx(tx, performerInfo, invocationRes, applicationRes) | ||
if err != nil { | ||
return nil, wrapErr(TxCommitmentError, errors.Errorf("failed to perform: %v", err)) | ||
} | ||
} | ||
if params.validatingUtx { | ||
// Save transaction to in-mem storage. | ||
if err := a.rw.writeTransactionToMem(tx, !res.status); err != nil { | ||
return wrapErr(TxCommitmentError, errors.Errorf("failed to write transaction to in mem stor: %v", err)) | ||
if err := a.rw.writeTransactionToMem(tx, !applicationRes.status); err != nil { | ||
return nil, wrapErr(TxCommitmentError, errors.Errorf("failed to write transaction to in mem stor: %v", err)) | ||
} | ||
} else { | ||
// Count tx fee. | ||
if err := a.blockDiffer.countMinerFee(tx); err != nil { | ||
return wrapErr(TxCommitmentError, errors.Errorf("failed to count miner fee: %v", err)) | ||
return nil, wrapErr(TxCommitmentError, errors.Errorf("failed to count miner fee: %v", err)) | ||
} | ||
// Save transaction to storage. | ||
if err := a.rw.writeTransaction(tx, !res.status); err != nil { | ||
return wrapErr(TxCommitmentError, errors.Errorf("failed to write transaction to storage: %v", err)) | ||
if err := a.rw.writeTransaction(tx, !applicationRes.status); err != nil { | ||
return nil, wrapErr(TxCommitmentError, errors.Errorf("failed to write transaction to storage: %v", err)) | ||
} | ||
} | ||
return nil | ||
return snapshot, nil | ||
} | ||
|
||
func (a *txAppender) verifyWavesTxSigAndData(tx proto.Transaction, params *appendTxParams, accountHasVerifierScript bool) error { | ||
|
@@ -405,18 +411,19 @@ type appendTxParams struct { | |
invokeExpressionActivated bool // TODO: check feature naming | ||
validatingUtx bool // if validatingUtx == false then chans MUST be initialized with non nil value | ||
stateActionsCounterInBlock *proto.StateActionsCounter | ||
currentMinerPK crypto.PublicKey | ||
} | ||
|
||
func (a *txAppender) handleInvokeOrExchangeTransaction(tx proto.Transaction, fallibleInfo *fallibleValidationParams) (*applicationResult, error) { | ||
applicationRes, err := a.handleFallible(tx, fallibleInfo) | ||
func (a *txAppender) handleInvokeOrExchangeTransaction(tx proto.Transaction, fallibleInfo *fallibleValidationParams) (*invocationResult, *applicationResult, error) { | ||
invocationRes, applicationRes, err := a.handleFallible(tx, fallibleInfo) | ||
if err != nil { | ||
msg := "fallible validation failed" | ||
if txID, err2 := tx.GetID(a.settings.AddressSchemeCharacter); err2 == nil { | ||
msg = fmt.Sprintf("fallible validation failed for transaction '%s'", base58.Encode(txID)) | ||
} | ||
return nil, errs.Extend(err, msg) | ||
return nil, nil, errs.Extend(err, msg) | ||
} | ||
return applicationRes, nil | ||
return invocationRes, applicationRes, nil | ||
} | ||
|
||
func (a *txAppender) handleDefaultTransaction(tx proto.Transaction, params *appendTxParams, accountHasVerifierScript bool) (*applicationResult, error) { | ||
|
@@ -470,13 +477,14 @@ func (a *txAppender) appendTx(tx proto.Transaction, params *appendTxParams) erro | |
|
||
// Check tx against state, check tx scripts, calculate balance changes. | ||
var applicationRes *applicationResult | ||
var invocationResult *invocationResult | ||
needToValidateBalanceDiff := false | ||
switch tx.GetTypeInfo().Type { | ||
case proto.InvokeScriptTransaction, proto.InvokeExpressionTransaction, proto.ExchangeTransaction: | ||
// Invoke and Exchange transactions should be handled differently. | ||
// They may fail, and will be saved to blockchain anyway. | ||
fallibleInfo := &fallibleValidationParams{appendTxParams: params, senderScripted: accountHasVerifierScript, senderAddress: senderAddr} | ||
applicationRes, err = a.handleInvokeOrExchangeTransaction(tx, fallibleInfo) | ||
invocationResult, applicationRes, err = a.handleInvokeOrExchangeTransaction(tx, fallibleInfo) | ||
if err != nil { | ||
return errors.Wrap(err, "failed to handle invoke or exchange transaction") | ||
} | ||
|
@@ -507,7 +515,7 @@ func (a *txAppender) appendTx(tx proto.Transaction, params *appendTxParams) erro | |
senderScripted: accountHasVerifierScript, | ||
senderAddress: senderAddr, | ||
} | ||
applicationRes, err = a.handleInvokeOrExchangeTransaction(tx, fallibleInfo) | ||
invocationResult, applicationRes, err = a.handleInvokeOrExchangeTransaction(tx, fallibleInfo) | ||
if err != nil { | ||
return errors.Wrapf(err, "failed to handle ethereum invoke script transaction (type %s) with id %s, on height %d", | ||
ethTx.TxKind.String(), ethTx.ID.String(), params.checkerInfo.height+1) | ||
|
@@ -540,10 +548,17 @@ func (a *txAppender) appendTx(tx proto.Transaction, params *appendTxParams) erro | |
if err != nil { | ||
return errs.Extend(err, "get transaction id") | ||
} | ||
if err := a.commitTxApplication(tx, params, applicationRes); err != nil { | ||
|
||
// invocationResult may be empty if it was not an Invoke Transaction | ||
snapshot, err := a.commitTxApplication(tx, params, invocationResult, applicationRes) | ||
if err != nil { | ||
zap.S().Errorf("failed to commit transaction (id %s) after successful validation; this should NEVER happen", base58.Encode(txID)) | ||
return err | ||
} | ||
// a temporary dummy for linters | ||
if len(snapshot) > 1000 { | ||
zap.S().Debug(snapshot) | ||
} | ||
// Store additional data for API: transaction by address. | ||
if !params.validatingUtx && a.buildApiData { | ||
if err := a.saveTransactionIdByAddresses(applicationRes.changes.addresses(), txID, blockID); err != nil { | ||
|
@@ -553,6 +568,29 @@ func (a *txAppender) appendTx(tx proto.Transaction, params *appendTxParams) erro | |
return nil | ||
} | ||
|
||
// rewards and 60% of the fee to the previous miner | ||
func (a *txAppender) createInitialBlockSnapshot(minerAndRewardDiff txDiff) (TransactionSnapshot, error) { | ||
addrWavesBalanceDiff, _, err := addressBalanceDiffFromTxDiff(minerAndRewardDiff, a.settings.AddressSchemeCharacter) | ||
if err != nil { | ||
return nil, errors.Wrap(err, "failed to create balance diff from tx diff") | ||
} | ||
// add miner address to the diff | ||
var snapshot TransactionSnapshot | ||
for wavesAddress, diffAmount := range addrWavesBalanceDiff { | ||
|
||
fullBalance, err := a.stor.balances.wavesBalance(wavesAddress.ID()) | ||
if err != nil { | ||
return nil, errors.Wrap(err, "failed to receive sender's waves balance") | ||
} | ||
newBalance := &WavesBalanceSnapshot{ | ||
Address: wavesAddress, | ||
Balance: uint64(int64(fullBalance.balance) + diffAmount.balance), | ||
} | ||
snapshot = append(snapshot, newBalance) | ||
} | ||
return snapshot, nil | ||
} | ||
|
||
func (a *txAppender) appendBlock(params *appendBlockParams) error { | ||
// Reset block complexity counter. | ||
defer func() { | ||
|
@@ -588,12 +626,21 @@ func (a *txAppender) appendBlock(params *appendBlockParams) error { | |
// Create miner balance diff. | ||
// This adds 60% of prev block fees as very first balance diff of the current block | ||
// in case NG is activated, or empty diff otherwise. | ||
minerDiff, err := a.blockDiffer.createMinerDiff(params.block, hasParent) | ||
minerAndRewardDiff, err := a.blockDiffer.createMinerAndRewardDiff(params.block, hasParent) | ||
if err != nil { | ||
return err | ||
} | ||
// create the initial snapshot | ||
initialSnapshot, err := a.createInitialBlockSnapshot(minerAndRewardDiff) | ||
if err != nil { | ||
return errors.Wrap(err, "failed to create initial snapshot") | ||
} | ||
// a temporary dummy for linters | ||
if len(initialSnapshot) > 100 { | ||
zap.S().Debug(initialSnapshot) | ||
} | ||
Comment on lines
+639
to
+642
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. And here |
||
// Save miner diff first. | ||
if err := a.diffStor.saveTxDiff(minerDiff); err != nil { | ||
if err := a.diffStor.saveTxDiff(minerAndRewardDiff); err != nil { | ||
return err | ||
} | ||
blockInfo, err := a.currentBlockInfo() | ||
|
@@ -633,13 +680,14 @@ func (a *txAppender) appendBlock(params *appendBlockParams) error { | |
invokeExpressionActivated: invokeExpressionActivated, | ||
validatingUtx: false, | ||
stateActionsCounterInBlock: stateActionsCounterInBlock, | ||
currentMinerPK: params.block.GeneratorPublicKey, | ||
} | ||
if err := a.appendTx(tx, appendTxArgs); err != nil { | ||
return err | ||
} | ||
} | ||
// Save fee distribution of this block. | ||
// This will be needed for createMinerDiff() of next block due to NG. | ||
// This will be needed for createMinerAndRewardDiff() of next block due to NG. | ||
if err := a.blockDiffer.saveCurFeeDistr(params.block); err != nil { | ||
return err | ||
} | ||
|
@@ -669,7 +717,7 @@ type applicationResult struct { | |
changes txBalanceChanges | ||
} | ||
|
||
func (a *txAppender) handleInvoke(tx proto.Transaction, info *fallibleValidationParams) (*applicationResult, error) { | ||
func (a *txAppender) handleInvoke(tx proto.Transaction, info *fallibleValidationParams) (*invocationResult, *applicationResult, error) { | ||
var ID crypto.Digest | ||
switch t := tx.(type) { | ||
case *proto.InvokeScriptWithProofs: | ||
|
@@ -681,17 +729,17 @@ func (a *txAppender) handleInvoke(tx proto.Transaction, info *fallibleValidation | |
case *proto.EthereumInvokeScriptTxKind: | ||
ID = *t.ID | ||
default: | ||
return nil, errors.Errorf("unexpected ethereum tx kind (%T)", tx) | ||
return nil, nil, errors.Errorf("unexpected ethereum tx kind (%T)", tx) | ||
} | ||
default: | ||
return nil, errors.Errorf("failed to handle invoke: wrong type of transaction (%T)", tx) | ||
return nil, nil, errors.Errorf("failed to handle invoke: wrong type of transaction (%T)", tx) | ||
} | ||
res, err := a.ia.applyInvokeScript(tx, info) | ||
invocationRes, applicationRes, err := a.ia.applyInvokeScript(tx, info) | ||
if err != nil { | ||
zap.S().Debugf("failed to apply InvokeScript transaction %s to state: %v", ID.String(), err) | ||
return nil, err | ||
return nil, nil, err | ||
} | ||
return res, nil | ||
return invocationRes, applicationRes, nil | ||
} | ||
|
||
func (a *txAppender) countExchangeScriptsRuns(scriptsRuns uint64) (uint64, error) { | ||
|
@@ -798,19 +846,20 @@ func (a *txAppender) handleExchange(tx proto.Transaction, info *fallibleValidati | |
return &applicationResult{true, scriptsRuns, successfulChanges}, nil | ||
} | ||
|
||
func (a *txAppender) handleFallible(tx proto.Transaction, info *fallibleValidationParams) (*applicationResult, error) { | ||
func (a *txAppender) handleFallible(tx proto.Transaction, info *fallibleValidationParams) (*invocationResult, *applicationResult, error) { | ||
if info.acceptFailed { | ||
if err := a.checkTxFees(tx, info); err != nil { | ||
return nil, err | ||
return nil, nil, err | ||
} | ||
} | ||
switch tx.GetTypeInfo().Type { | ||
case proto.InvokeScriptTransaction, proto.InvokeExpressionTransaction, proto.EthereumMetamaskTransaction: | ||
return a.handleInvoke(tx, info) | ||
case proto.ExchangeTransaction: | ||
return a.handleExchange(tx, info) | ||
applicationRes, err := a.handleExchange(tx, info) | ||
return nil, applicationRes, err | ||
} | ||
return nil, errors.New("transaction is not fallible") | ||
return nil, nil, errors.New("transaction is not fallible") | ||
} | ||
|
||
// For UTX validation. | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please, replace it with
_ = initialSnapshot
and addTODO
.