github.com/koko1123/flow-go-1@v0.29.6/fvm/derived/derived_block_data.go (about) 1 package derived 2 3 import ( 4 "fmt" 5 6 "github.com/onflow/cadence/runtime/common" 7 "github.com/onflow/cadence/runtime/interpreter" 8 9 "github.com/koko1123/flow-go-1/fvm/state" 10 ) 11 12 // ProgramDependencies are the locations of the programs this program depends on. 13 type ProgramDependencies map[common.Address]struct{} 14 15 // AddDependency adds the address as a dependency. 16 func (d ProgramDependencies) AddDependency(address common.Address) { 17 d[address] = struct{}{} 18 } 19 20 // Merge merges current dependencies with other dependencies. 21 func (d ProgramDependencies) Merge(other ProgramDependencies) { 22 for address := range other { 23 d[address] = struct{}{} 24 } 25 } 26 27 type Program struct { 28 *interpreter.Program 29 30 Dependencies ProgramDependencies 31 } 32 33 // DerivedBlockData is a simple fork-aware OCC database for "caching" derived 34 // data for a particular block. 35 type DerivedBlockData struct { 36 programs *DerivedDataTable[common.AddressLocation, *Program] 37 38 meterParamOverrides *DerivedDataTable[struct{}, MeterParamOverrides] 39 } 40 41 // DerivedTransactionData is the derived data scratch space for a single 42 // transaction. 43 type DerivedTransactionData struct { 44 programs *TableTransaction[ 45 common.AddressLocation, 46 *Program, 47 ] 48 49 // There's only a single entry in this table. For simplicity, we'll use 50 // struct{} as the entry's key. 51 meterParamOverrides *TableTransaction[struct{}, MeterParamOverrides] 52 } 53 54 func NewEmptyDerivedBlockData() *DerivedBlockData { 55 return &DerivedBlockData{ 56 programs: NewEmptyTable[ 57 common.AddressLocation, 58 *Program, 59 ](), 60 meterParamOverrides: NewEmptyTable[ 61 struct{}, 62 MeterParamOverrides, 63 ](), 64 } 65 } 66 67 // This variant is needed by the chunk verifier, which does not start at the 68 // beginning of the block. 69 func NewEmptyDerivedBlockDataWithTransactionOffset(offset uint32) *DerivedBlockData { 70 return &DerivedBlockData{ 71 programs: NewEmptyTableWithOffset[ 72 common.AddressLocation, 73 *Program, 74 ](offset), 75 meterParamOverrides: NewEmptyTableWithOffset[ 76 struct{}, 77 MeterParamOverrides, 78 ](offset), 79 } 80 } 81 82 func (block *DerivedBlockData) NewChildDerivedBlockData() *DerivedBlockData { 83 return &DerivedBlockData{ 84 programs: block.programs.NewChildTable(), 85 meterParamOverrides: block.meterParamOverrides.NewChildTable(), 86 } 87 } 88 89 func (block *DerivedBlockData) NewSnapshotReadDerivedTransactionData( 90 snapshotTime LogicalTime, 91 executionTime LogicalTime, 92 ) ( 93 *DerivedTransactionData, 94 error, 95 ) { 96 txnPrograms, err := block.programs.NewSnapshotReadTableTransaction( 97 snapshotTime, 98 executionTime) 99 if err != nil { 100 return nil, err 101 } 102 103 txnMeterParamOverrides, err := block.meterParamOverrides.NewSnapshotReadTableTransaction( 104 snapshotTime, 105 executionTime) 106 if err != nil { 107 return nil, err 108 } 109 110 return &DerivedTransactionData{ 111 programs: txnPrograms, 112 meterParamOverrides: txnMeterParamOverrides, 113 }, nil 114 } 115 116 func (block *DerivedBlockData) NewDerivedTransactionData( 117 snapshotTime LogicalTime, 118 executionTime LogicalTime, 119 ) ( 120 *DerivedTransactionData, 121 error, 122 ) { 123 txnPrograms, err := block.programs.NewTableTransaction( 124 snapshotTime, 125 executionTime) 126 if err != nil { 127 return nil, err 128 } 129 130 txnMeterParamOverrides, err := block.meterParamOverrides.NewTableTransaction( 131 snapshotTime, 132 executionTime) 133 if err != nil { 134 return nil, err 135 } 136 137 return &DerivedTransactionData{ 138 programs: txnPrograms, 139 meterParamOverrides: txnMeterParamOverrides, 140 }, nil 141 } 142 143 func (block *DerivedBlockData) NextTxIndexForTestingOnly() uint32 { 144 // NOTE: We can use next tx index from any table since they are identical. 145 return block.programs.NextTxIndexForTestingOnly() 146 } 147 148 func (block *DerivedBlockData) GetProgramForTestingOnly( 149 addressLocation common.AddressLocation, 150 ) *invalidatableEntry[*Program] { 151 return block.programs.GetForTestingOnly(addressLocation) 152 } 153 154 func (transaction *DerivedTransactionData) GetProgram( 155 addressLocation common.AddressLocation, 156 ) ( 157 *Program, 158 *state.State, 159 bool, 160 ) { 161 return transaction.programs.Get(addressLocation) 162 } 163 164 func (transaction *DerivedTransactionData) SetProgram( 165 addressLocation common.AddressLocation, 166 program *Program, 167 state *state.State, 168 ) { 169 transaction.programs.Set(addressLocation, program, state) 170 } 171 172 func (transaction *DerivedTransactionData) AddInvalidator( 173 invalidator TransactionInvalidator, 174 ) { 175 if invalidator == nil { 176 return 177 } 178 179 transaction.programs.AddInvalidator(invalidator.ProgramInvalidator()) 180 transaction.meterParamOverrides.AddInvalidator( 181 invalidator.MeterParamOverridesInvalidator()) 182 } 183 184 func (transaction *DerivedTransactionData) GetMeterParamOverrides( 185 txnState *state.TransactionState, 186 getMeterParamOverrides ValueComputer[struct{}, MeterParamOverrides], 187 ) ( 188 MeterParamOverrides, 189 error, 190 ) { 191 return transaction.meterParamOverrides.GetOrCompute( 192 txnState, 193 struct{}{}, 194 getMeterParamOverrides) 195 } 196 197 func (transaction *DerivedTransactionData) Validate() error { 198 err := transaction.programs.Validate() 199 if err != nil { 200 return fmt.Errorf("programs validate failed: %w", err) 201 } 202 203 err = transaction.meterParamOverrides.Validate() 204 if err != nil { 205 return fmt.Errorf("meter param overrides validate failed: %w", err) 206 } 207 208 return nil 209 } 210 211 func (transaction *DerivedTransactionData) Commit() error { 212 err := transaction.programs.Commit() 213 if err != nil { 214 return fmt.Errorf("programs commit failed: %w", err) 215 } 216 217 err = transaction.meterParamOverrides.Commit() 218 if err != nil { 219 return fmt.Errorf("meter param overrides commit failed: %w", err) 220 } 221 222 return nil 223 }