From a2a15eab00f57724949b45e3c61c976060e8d8cc Mon Sep 17 00:00:00 2001 From: Tolik Zinovyev Date: Fri, 22 Oct 2021 15:42:40 -0400 Subject: [PATCH 1/2] Do final validation in endOfBlock(). --- ledger/internal/eval.go | 101 +++++++++++++++------------------ ledger/internal/evalindexer.go | 6 -- 2 files changed, 45 insertions(+), 62 deletions(-) diff --git a/ledger/internal/eval.go b/ledger/internal/eval.go index bc9af21b61..7a7ab6b776 100644 --- a/ledger/internal/eval.go +++ b/ledger/internal/eval.go @@ -1053,6 +1053,8 @@ func (eval *BlockEvaluator) TestingTxnCounter() uint64 { // Call "endOfBlock" after all the block's rewards and transactions are processed. func (eval *BlockEvaluator) endOfBlock() error { + eval.state.mods.OptimizeAllocatedMemory(eval.proto) + if eval.generate { var err error eval.block.TxnRoot, err = eval.block.PaysetCommit() @@ -1092,6 +1094,49 @@ func (eval *BlockEvaluator) endOfBlock() error { return err } + if eval.validate { + // check commitments + txnRoot, err := eval.block.PaysetCommit() + if err != nil { + return err + } + if txnRoot != eval.block.TxnRoot { + return fmt.Errorf("txn root wrong: %v != %v", txnRoot, eval.block.TxnRoot) + } + + var expectedTxnCount uint64 + if eval.proto.TxnCounter { + expectedTxnCount = eval.state.txnCounter() + } + if eval.block.TxnCounter != expectedTxnCount { + return fmt.Errorf("txn count wrong: %d != %d", eval.block.TxnCounter, expectedTxnCount) + } + + expectedVoters, expectedVotersWeight, err := eval.compactCertVotersAndTotal() + if err != nil { + return err + } + if eval.block.CompactCert[protocol.CompactCertBasic].CompactCertVoters != expectedVoters { + return fmt.Errorf("CompactCertVoters wrong: %v != %v", eval.block.CompactCert[protocol.CompactCertBasic].CompactCertVoters, expectedVoters) + } + if eval.block.CompactCert[protocol.CompactCertBasic].CompactCertVotersTotal != expectedVotersWeight { + return fmt.Errorf("CompactCertVotersTotal wrong: %v != %v", eval.block.CompactCert[protocol.CompactCertBasic].CompactCertVotersTotal, expectedVotersWeight) + } + if eval.block.CompactCert[protocol.CompactCertBasic].CompactCertNextRound != eval.state.compactCertNext() { + return fmt.Errorf("CompactCertNextRound wrong: %v != %v", eval.block.CompactCert[protocol.CompactCertBasic].CompactCertNextRound, eval.state.compactCertNext()) + } + for ccType := range eval.block.CompactCert { + if ccType != protocol.CompactCertBasic { + return fmt.Errorf("CompactCertType %d unexpected", ccType) + } + } + } + + err = eval.state.CalculateTotals() + if err != nil { + return err + } + return nil } @@ -1187,7 +1232,6 @@ func (eval *BlockEvaluator) validateExpiredOnlineAccounts() error { // resetExpiredOnlineAccountsParticipationKeys after all transactions and rewards are processed, modify the accounts so that their status is offline func (eval *BlockEvaluator) resetExpiredOnlineAccountsParticipationKeys() error { - expectedMaxNumberOfExpiredAccounts := eval.proto.MaxProposedExpiredOnlineAccounts lengthOfExpiredParticipationAccounts := len(eval.block.ParticipationUpdates.ExpiredParticipationAccounts) @@ -1216,51 +1260,6 @@ func (eval *BlockEvaluator) resetExpiredOnlineAccountsParticipationKeys() error return nil } -// FinalValidation does the validation that must happen after the block is built and all state updates are computed -func (eval *BlockEvaluator) finalValidation() error { - eval.state.mods.OptimizeAllocatedMemory(eval.proto) - if eval.validate { - // check commitments - txnRoot, err := eval.block.PaysetCommit() - if err != nil { - return err - } - if txnRoot != eval.block.TxnRoot { - return fmt.Errorf("txn root wrong: %v != %v", txnRoot, eval.block.TxnRoot) - } - - var expectedTxnCount uint64 - if eval.proto.TxnCounter { - expectedTxnCount = eval.state.txnCounter() - } - if eval.block.TxnCounter != expectedTxnCount { - return fmt.Errorf("txn count wrong: %d != %d", eval.block.TxnCounter, expectedTxnCount) - } - - expectedVoters, expectedVotersWeight, err := eval.compactCertVotersAndTotal() - if err != nil { - return err - } - if eval.block.CompactCert[protocol.CompactCertBasic].CompactCertVoters != expectedVoters { - return fmt.Errorf("CompactCertVoters wrong: %v != %v", eval.block.CompactCert[protocol.CompactCertBasic].CompactCertVoters, expectedVoters) - } - if eval.block.CompactCert[protocol.CompactCertBasic].CompactCertVotersTotal != expectedVotersWeight { - return fmt.Errorf("CompactCertVotersTotal wrong: %v != %v", eval.block.CompactCert[protocol.CompactCertBasic].CompactCertVotersTotal, expectedVotersWeight) - } - if eval.block.CompactCert[protocol.CompactCertBasic].CompactCertNextRound != eval.state.compactCertNext() { - return fmt.Errorf("CompactCertNextRound wrong: %v != %v", eval.block.CompactCert[protocol.CompactCertBasic].CompactCertNextRound, eval.state.compactCertNext()) - } - for ccType := range eval.block.CompactCert { - if ccType != protocol.CompactCertBasic { - return fmt.Errorf("CompactCertType %d unexpected", ccType) - } - } - - } - - return eval.state.CalculateTotals() -} - // GenerateBlock produces a complete block from the BlockEvaluator. This is // used during proposal to get an actual block that will be proposed, after // feeding in tentative transactions into this block evaluator. @@ -1282,11 +1281,6 @@ func (eval *BlockEvaluator) GenerateBlock() (*ledgercore.ValidatedBlock, error) return nil, err } - err = eval.finalValidation() - if err != nil { - return nil, err - } - vb := ledgercore.MakeValidatedBlock(eval.block, eval.state.deltas()) eval.blockGenerated = true proto, ok := config.Consensus[eval.block.BlockHeader.CurrentProtocol] @@ -1448,11 +1442,6 @@ transactionGroupLoop: } } - err = eval.finalValidation() - if err != nil { - return ledgercore.StateDelta{}, err - } - return eval.state.deltas(), nil } diff --git a/ledger/internal/evalindexer.go b/ledger/internal/evalindexer.go index a89cdf7798..454ae2d7a5 100644 --- a/ledger/internal/evalindexer.go +++ b/ledger/internal/evalindexer.go @@ -47,11 +47,5 @@ func (eval *BlockEvaluator) ProcessBlockForIndexer(block *bookkeeping.Block) (le fmt.Errorf("ProcessBlockForIndexer() err: %w", err) } - err = eval.finalValidation() - if err != nil { - return ledgercore.StateDelta{}, []transactions.SignedTxnInBlock{}, - fmt.Errorf("ProcessBlockForIndexer() err: %w", err) - } - return eval.state.deltas(), eval.block.Payset, nil } From 7a1957aa42d84d0a3e2f8b556e645726558f204a Mon Sep 17 00:00:00 2001 From: Tolik Zinovyev Date: Fri, 29 Oct 2021 16:44:41 -0400 Subject: [PATCH 2/2] Move OptimizeAllocatedMemory(). --- ledger/internal/eval.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ledger/internal/eval.go b/ledger/internal/eval.go index 7a7ab6b776..1af42e0785 100644 --- a/ledger/internal/eval.go +++ b/ledger/internal/eval.go @@ -1053,8 +1053,6 @@ func (eval *BlockEvaluator) TestingTxnCounter() uint64 { // Call "endOfBlock" after all the block's rewards and transactions are processed. func (eval *BlockEvaluator) endOfBlock() error { - eval.state.mods.OptimizeAllocatedMemory(eval.proto) - if eval.generate { var err error eval.block.TxnRoot, err = eval.block.PaysetCommit() @@ -1094,6 +1092,8 @@ func (eval *BlockEvaluator) endOfBlock() error { return err } + eval.state.mods.OptimizeAllocatedMemory(eval.proto) + if eval.validate { // check commitments txnRoot, err := eval.block.PaysetCommit()