github.com/dim4egster/coreth@v0.10.2/plugin/evm/block.go (about) 1 // (c) 2019-2020, Ava Labs, Inc. All rights reserved. 2 // See the file LICENSE for licensing terms. 3 4 package evm 5 6 import ( 7 "fmt" 8 "math/big" 9 "time" 10 11 "github.com/ethereum/go-ethereum/common" 12 "github.com/ethereum/go-ethereum/log" 13 "github.com/ethereum/go-ethereum/rlp" 14 15 "github.com/dim4egster/coreth/core/types" 16 17 "github.com/dim4egster/qmallgo/ids" 18 "github.com/dim4egster/qmallgo/snow/choices" 19 ) 20 21 var ( 22 bonusBlockMainnetHeights = make(map[uint64]ids.ID) 23 // first height that processed a TX included on a 24 // bonus block is the canonical height for that TX. 25 canonicalBlockMainnetHeights = []uint64{ 26 102928, 103035, 103038, 103114, 103193, 27 103234, 103338, 103444, 103480, 103491, 28 103513, 103533, 103535, 103538, 103541, 29 103546, 103571, 103572, 103619, 30 103287, 103624, 103591, 31 } 32 ) 33 34 func init() { 35 mainnetBonusBlocks := map[uint64]string{ 36 102972: "Njm9TcLUXRojZk8YhEM6ksvfiPdC1TME4zJvGaDXgzMCyB6oB", 37 103105: "BYqLB6xpqy7HsAgP2XNfGE8Ubg1uEzse5mBPTSJH9z5s8pvMa", 38 103143: "AfWvJH3rB2fdHuPWQp6qYNCFVT29MooQPRigD88rKKwUDEDhq", 39 103183: "2KPW9G5tiNF14tZNfG4SqHuQrtUYVZyxuof37aZ7AnTKrQdsHn", 40 103197: "pE93VXY3N5QKfwsEFcM9i59UpPFgeZ8nxpJNaGaDQyDgsscNf", 41 103203: "2czmtnBS44VCWNRFUM89h4Fe9m3ZeZVYyh7Pe3FhNqjRNgPXhZ", 42 103208: "esx5J962LtYm2aSrskpLai5e4CMMsaS1dsu9iuLGJ3KWgSu2M", 43 103209: "DK9NqAJGry1wAo767uuYc1dYXAjUhzwka6vi8d9tNheqzGUTd", 44 103259: "i1HoerJ1axognkUKKL58FvF9aLrbZKtv7TdKLkT5kgzoeU1vB", 45 103261: "2DpCuBaH94zKKFNY2XTs4GeJcwsEv6qT2DHc59S8tdg97GZpcJ", 46 103266: "2ez4CA7w4HHr8SSobHQUAwFgj2giRNjNFUZK9JvrZFa1AuRj6X", 47 103287: "2QBNMMFJmhVHaGF45GAPszKyj1gK6ToBERRxYvXtM7yfrdUGPK", 48 103339: "2pSjfo7rkFCfZ2CqAxqfw8vqM2CU2nVLHrFZe3rwxz43gkVuGo", 49 103346: "2SiSziHHqPjb1qkw7CdGYupokiYpd2b7mMqRiyszurctcA5AKr", 50 103350: "2F5tSQbdTfhZxvkxZqdFp7KR3FrJPKEsDLQK7KtPhNXj1EZAh4", 51 103358: "2tCe88ur6MLQcVgwE5XxoaHiTGtSrthwKN3SdbHE4kWiQ7MSTV", 52 103437: "21o2fVTnzzmtgXqkV1yuQeze7YEQhR5JB31jVVD9oVUnaaV8qm", 53 103472: "2nG4exd9eUoAGzELfksmBR8XDCKhohY1uDKRFzEXJG4M8p3qA7", 54 103478: "63YLdYXfXc5tY3mwWLaDsbXzQHYmwWVxMP7HKbRh4Du3C2iM1", 55 103493: "soPweZ8DGaoUMjrnzjH3V2bypa7ZvvfqBan4UCsMUxMP759gw", 56 103514: "2dNkpQF4mooveyUDfBYQTBfsGDV4wkncQPpEw4kHKfSTSTo5x", 57 103536: "PJTkRrHvKZ1m4AQdPND1MBpUXpCrGN4DDmXmJQAiUrsxPoLQX", 58 103545: "22ck2Z7cC38hmBfX2v3jMWxun8eD8psNaicfYeokS67DxwmPTx", 59 103547: "pTf7gfk1ksj7bqMrLyMCij8FBKth1uRqQrtfykMFeXhx5xnrL", 60 103554: "9oZh4qyBCcVwSGyDoUzRAuausvPJN3xH6nopKS6bwYzMfLoQ2", 61 103555: "MjExz2z1qhwugc1tAyiGxRsCq4GvJwKfyyS29nr4tRVB8ooic", 62 103559: "cwJusfmn98TW3DjAbfLRN9utYR24KAQ82qpAXmVSvjHyJZuM2", 63 103561: "2YgxGHns7Z2hMMHJsPCgVXuJaL7x1b3gnHbmSCfCdyAcYGr6mx", 64 103563: "2AXxT3PSEnaYHNtBTnYrVTf24TtKDWjky9sqoFEhydrGXE9iKH", 65 103564: "Ry2sfjFfGEnJxRkUGFSyZNn7GR3m4aKAf1scDW2uXSNQB568Y", 66 103569: "21Jys8UNURmtckKSV89S2hntEWymJszrLQbdLaNcbXcxDAsQSa", 67 103570: "sg6wAwFBsPQiS5Yfyh41cVkCRQbrrXsxXmeNyQ1xkunf2sdyv", 68 103575: "z3BgePPpCXq1mRBRvUi28rYYxnEtJizkUEHnDBrcZeVA7MFVk", 69 103577: "uK5Ff9iBfDtREpVv9NgCQ1STD1nzLJG3yrfibHG4mGvmybw6f", 70 103578: "Qv5v5Ru8ArfnWKB1w6s4G5EYPh7TybHJtF6UsVwAkfvZFoqmj", 71 103582: "7KCZKBpxovtX9opb7rMRie9WmW5YbZ8A4HwBBokJ9eSHpZPqx", 72 103587: "2AfTQ2FXNj9bkSUQnud9pFXULx6EbF7cbbw6i3ayvc2QNhgxfF", 73 103590: "2gTygYckZgFZfN5QQWPaPBD3nabqjidV55mwy1x1Nd4JmJAwaM", 74 103591: "2cUPPHy1hspr2nAKpQrrAEisLKkaWSS9iF2wjNFyFRs8vnSkKK", 75 103594: "5MptSdP6dBMPSwk9GJjeVe39deZJTRh9i82cgNibjeDffrrTf", 76 103597: "2J8z7HNv4nwh82wqRGyEHqQeuw4wJ6mCDCSvUgusBu35asnshK", 77 103598: "2i2FP6nJyvhX9FR15qN2D9AVoK5XKgBD2i2AQ7FoSpfowxvQDX", 78 103603: "2v3smb35s4GLACsK4Zkd2RcLBLdWA4huqrvq8Y3VP4CVe8kfTM", 79 103604: "b7XfDDLgwB12DfL7UTWZoxwBpkLPL5mdHtXngD94Y2RoeWXSh", 80 103607: "PgaRk1UAoUvRybhnXsrLq5t6imWhEa6ksNjbN6hWgs4qPrSzm", 81 103612: "2oueNTj4dUE2FFtGyPpawnmCCsy6EUQeVHVLZy8NHeQmkAciP4", 82 103614: "2YHZ1KymFjiBhpXzgt6HXJhLSt5SV9UQ4tJuUNjfN1nQQdm5zz", 83 103617: "amgH2C1s9H3Av7vSW4y7n7TXb9tKyKHENvrDXutgNN6nsejgc", 84 103618: "fV8k1U8oQDmfVwK66kAwN73aSsWiWhm8quNpVnKmSznBycV2W", 85 103621: "Nzs93kFTvcXanFUp9Y8VQkKYnzmH8xykxVNFJTkdyAEeuxWbP", 86 103623: "2rAsBj3emqQa13CV8r5fTtHogs4sXnjvbbXVzcKPi3WmzhpK9D", 87 103624: "2JbuExUGKW5mYz5KfXATwq1ibRDimgks9wEdYGNSC6Ttey1R4U", 88 103627: "tLLijh7oKfvWT1yk9zRv4FQvuQ5DAiuvb5kHCNN9zh4mqkFMG", 89 103628: "dWBsRYRwFrcyi3DPdLoHsL67QkZ5h86hwtVfP94ZBaY18EkmF", 90 103629: "XMoEsew2DhSgQaydcJFJUQAQYP8BTNTYbEJZvtbrV2QsX7iE3", 91 103630: "2db2wMbVAoCc5EUJrsBYWvNZDekqyY8uNpaaVapdBAQZ5oRaou", 92 103633: "2QiHZwLhQ3xLuyyfcdo5yCUfoSqWDvRZox5ECU19HiswfroCGp", 93 } 94 95 for height, blkIDStr := range mainnetBonusBlocks { 96 blkID, err := ids.FromString(blkIDStr) 97 if err != nil { 98 panic(err) 99 } 100 bonusBlockMainnetHeights[height] = blkID 101 } 102 } 103 104 // Block implements the snowman.Block interface 105 type Block struct { 106 id ids.ID 107 ethBlock *types.Block 108 vm *VM 109 status choices.Status 110 atomicTxs []*Tx 111 } 112 113 // newBlock returns a new Block wrapping the ethBlock type and implementing the snowman.Block interface 114 func (vm *VM) newBlock(ethBlock *types.Block) (*Block, error) { 115 isApricotPhase5 := vm.chainConfig.IsApricotPhase5(new(big.Int).SetUint64(ethBlock.Time())) 116 atomicTxs, err := ExtractAtomicTxs(ethBlock.ExtData(), isApricotPhase5, vm.codec) 117 if err != nil { 118 return nil, err 119 } 120 121 return &Block{ 122 id: ids.ID(ethBlock.Hash()), 123 ethBlock: ethBlock, 124 vm: vm, 125 atomicTxs: atomicTxs, 126 }, nil 127 } 128 129 // ID implements the snowman.Block interface 130 func (b *Block) ID() ids.ID { return b.id } 131 132 // Accept implements the snowman.Block interface 133 func (b *Block) Accept() error { 134 vm := b.vm 135 136 // Although returning an error from Accept is considered fatal, it is good 137 // practice to cleanup the batch we were modifying in the case of an error. 138 defer vm.db.Abort() 139 140 b.status = choices.Accepted 141 log.Debug(fmt.Sprintf("Accepting block %s (%s) at height %d", b.ID().Hex(), b.ID(), b.Height())) 142 if err := vm.blockChain.Accept(b.ethBlock); err != nil { 143 return fmt.Errorf("chain could not accept %s: %w", b.ID(), err) 144 } 145 if err := vm.acceptedBlockDB.Put(lastAcceptedKey, b.id[:]); err != nil { 146 return fmt.Errorf("failed to put %s as the last accepted block: %w", b.ID(), err) 147 } 148 149 for _, tx := range b.atomicTxs { 150 // Remove the accepted transaction from the mempool 151 vm.mempool.RemoveTx(tx) 152 } 153 154 // Update VM state for atomic txs in this block. This includes updating the 155 // atomic tx repo, atomic trie, and shared memory. 156 atomicState, err := b.vm.atomicBackend.GetVerifiedAtomicState(common.Hash(b.ID())) 157 if err != nil { 158 // should never occur since [b] must be verified before calling Accept 159 return err 160 } 161 commitBatch, err := b.vm.db.CommitBatch() 162 if err != nil { 163 return fmt.Errorf("could not create commit batch processing block[%s]: %w", b.ID(), err) 164 } 165 return atomicState.Accept(commitBatch) 166 } 167 168 // Reject implements the snowman.Block interface 169 // If [b] contains an atomic transaction, attempt to re-issue it 170 func (b *Block) Reject() error { 171 b.status = choices.Rejected 172 log.Debug(fmt.Sprintf("Rejecting block %s (%s) at height %d", b.ID().Hex(), b.ID(), b.Height())) 173 for _, tx := range b.atomicTxs { 174 b.vm.mempool.RemoveTx(tx) 175 if err := b.vm.issueTx(tx, false /* set local to false when re-issuing */); err != nil { 176 log.Debug("Failed to re-issue transaction in rejected block", "txID", tx.ID(), "err", err) 177 } 178 } 179 atomicState, err := b.vm.atomicBackend.GetVerifiedAtomicState(common.Hash(b.ID())) 180 if err != nil { 181 // should never occur since [b] must be verified before calling Reject 182 return err 183 } 184 if err := atomicState.Reject(); err != nil { 185 return err 186 } 187 return b.vm.blockChain.Reject(b.ethBlock) 188 } 189 190 // SetStatus implements the InternalBlock interface allowing ChainState 191 // to set the status on an existing block 192 func (b *Block) SetStatus(status choices.Status) { b.status = status } 193 194 // Status implements the snowman.Block interface 195 func (b *Block) Status() choices.Status { 196 return b.status 197 } 198 199 // Parent implements the snowman.Block interface 200 func (b *Block) Parent() ids.ID { 201 return ids.ID(b.ethBlock.ParentHash()) 202 } 203 204 // Height implements the snowman.Block interface 205 func (b *Block) Height() uint64 { 206 return b.ethBlock.NumberU64() 207 } 208 209 // Timestamp implements the snowman.Block interface 210 func (b *Block) Timestamp() time.Time { 211 return time.Unix(int64(b.ethBlock.Time()), 0) 212 } 213 214 // syntacticVerify verifies that a *Block is well-formed. 215 func (b *Block) syntacticVerify() error { 216 if b == nil || b.ethBlock == nil { 217 return errInvalidBlock 218 } 219 220 header := b.ethBlock.Header() 221 rules := b.vm.chainConfig.AvalancheRules(header.Number, new(big.Int).SetUint64(header.Time)) 222 return b.vm.syntacticBlockValidator.SyntacticVerify(b, rules) 223 } 224 225 // Verify implements the snowman.Block interface 226 func (b *Block) Verify() error { 227 return b.verify(true) 228 } 229 230 func (b *Block) verify(writes bool) error { 231 if err := b.syntacticVerify(); err != nil { 232 return fmt.Errorf("syntactic block verification failed: %w", err) 233 } 234 235 err := b.vm.blockChain.InsertBlockManual(b.ethBlock, writes) 236 if err != nil || !writes { 237 // if an error occurred inserting the block into the chain 238 // or if we are not pinning to memory, unpin the atomic trie 239 // changes from memory (if they were pinned). 240 if atomicState, err := b.vm.atomicBackend.GetVerifiedAtomicState(b.ethBlock.Hash()); err == nil { 241 _ = atomicState.Reject() // ignore this error so we can return the original error instead. 242 } 243 } 244 return err 245 } 246 247 // Bytes implements the snowman.Block interface 248 func (b *Block) Bytes() []byte { 249 res, err := rlp.EncodeToBytes(b.ethBlock) 250 if err != nil { 251 panic(err) 252 } 253 return res 254 } 255 256 func (b *Block) String() string { return fmt.Sprintf("EVM block, ID = %s", b.ID()) }