github.com/onflow/flow-go@v0.35.7-crescendo-preview.23-atree-inlining/engine/execution/computation/committer/committer.go (about) 1 package committer 2 3 import ( 4 "fmt" 5 "sync" 6 7 "github.com/hashicorp/go-multierror" 8 9 "github.com/onflow/flow-go/engine/execution" 10 execState "github.com/onflow/flow-go/engine/execution/state" 11 "github.com/onflow/flow-go/fvm/storage/snapshot" 12 "github.com/onflow/flow-go/ledger" 13 "github.com/onflow/flow-go/ledger/common/convert" 14 "github.com/onflow/flow-go/model/flow" 15 "github.com/onflow/flow-go/module" 16 ) 17 18 type LedgerViewCommitter struct { 19 ledger ledger.Ledger 20 tracer module.Tracer 21 } 22 23 func NewLedgerViewCommitter( 24 ledger ledger.Ledger, 25 tracer module.Tracer, 26 ) *LedgerViewCommitter { 27 return &LedgerViewCommitter{ 28 ledger: ledger, 29 tracer: tracer, 30 } 31 } 32 33 func (committer *LedgerViewCommitter) CommitView( 34 snapshot *snapshot.ExecutionSnapshot, 35 baseStorageSnapshot execution.ExtendableStorageSnapshot, 36 ) ( 37 newCommit flow.StateCommitment, 38 proof []byte, 39 trieUpdate *ledger.TrieUpdate, 40 newStorageSnapshot execution.ExtendableStorageSnapshot, 41 err error, 42 ) { 43 var err1, err2 error 44 var wg sync.WaitGroup 45 wg.Add(1) 46 go func() { 47 proof, err2 = committer.collectProofs(snapshot, baseStorageSnapshot) 48 wg.Done() 49 }() 50 51 newCommit, trieUpdate, newStorageSnapshot, err1 = execState.CommitDelta( 52 committer.ledger, 53 snapshot, 54 baseStorageSnapshot) 55 wg.Wait() 56 57 if err1 != nil { 58 err = multierror.Append(err, err1) 59 } 60 if err2 != nil { 61 err = multierror.Append(err, err2) 62 } 63 return 64 } 65 66 func (committer *LedgerViewCommitter) collectProofs( 67 snapshot *snapshot.ExecutionSnapshot, 68 baseStorageSnapshot execution.ExtendableStorageSnapshot, 69 ) ( 70 proof []byte, 71 err error, 72 ) { 73 baseState := baseStorageSnapshot.Commitment() 74 // Reason for including AllRegisterIDs (read and written registers) instead of ReadRegisterIDs (only read registers): 75 // AllRegisterIDs returns deduplicated register IDs that were touched by both 76 // reads and writes during the block execution. 77 // Verification nodes only need the registers in the storage proof that were touched by reads 78 // in order to execute transactions in a chunk. However, without the registers touched 79 // by writes, especially the interim trie nodes for them, verification nodes won't be 80 // able to reconstruct the trie root hash of the execution state post execution. That's why 81 // the storage proof needs both read registers and write registers, which specifically is AllRegisterIDs 82 allIds := snapshot.AllRegisterIDs() 83 keys := make([]ledger.Key, 0, len(allIds)) 84 for _, id := range allIds { 85 keys = append(keys, convert.RegisterIDToLedgerKey(id)) 86 } 87 88 query, err := ledger.NewQuery(ledger.State(baseState), keys) 89 if err != nil { 90 return nil, fmt.Errorf("cannot create ledger query: %w", err) 91 } 92 93 return committer.ledger.Prove(query) 94 }