gitlab.com/flarenetwork/coreth@v0.1.1/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 "gitlab.com/flarenetwork/coreth/core/types" 16 "gitlab.com/flarenetwork/coreth/params" 17 18 "github.com/ava-labs/avalanchego/ids" 19 "github.com/ava-labs/avalanchego/snow/choices" 20 ) 21 22 var bonusBlocks = ids.Set{} 23 24 func init() { 25 blockIDStrs := []string{ 26 "XMoEsew2DhSgQaydcJFJUQAQYP8BTNTYbEJZvtbrV2QsX7iE3", 27 "2QiHZwLhQ3xLuyyfcdo5yCUfoSqWDvRZox5ECU19HiswfroCGp", 28 "tLLijh7oKfvWT1yk9zRv4FQvuQ5DAiuvb5kHCNN9zh4mqkFMG", 29 "2db2wMbVAoCc5EUJrsBYWvNZDekqyY8uNpaaVapdBAQZ5oRaou", 30 "2rAsBj3emqQa13CV8r5fTtHogs4sXnjvbbXVzcKPi3WmzhpK9D", 31 "amgH2C1s9H3Av7vSW4y7n7TXb9tKyKHENvrDXutgNN6nsejgc", 32 "dWBsRYRwFrcyi3DPdLoHsL67QkZ5h86hwtVfP94ZBaY18EkmF", 33 "PgaRk1UAoUvRybhnXsrLq5t6imWhEa6ksNjbN6hWgs4qPrSzm", 34 "b7XfDDLgwB12DfL7UTWZoxwBpkLPL5mdHtXngD94Y2RoeWXSh", 35 "2i2FP6nJyvhX9FR15qN2D9AVoK5XKgBD2i2AQ7FoSpfowxvQDX", 36 "2J8z7HNv4nwh82wqRGyEHqQeuw4wJ6mCDCSvUgusBu35asnshK", 37 "2cUPPHy1hspr2nAKpQrrAEisLKkaWSS9iF2wjNFyFRs8vnSkKK", 38 "2gTygYckZgFZfN5QQWPaPBD3nabqjidV55mwy1x1Nd4JmJAwaM", 39 "5MptSdP6dBMPSwk9GJjeVe39deZJTRh9i82cgNibjeDffrrTf", 40 "2v3smb35s4GLACsK4Zkd2RcLBLdWA4huqrvq8Y3VP4CVe8kfTM", 41 "7KCZKBpxovtX9opb7rMRie9WmW5YbZ8A4HwBBokJ9eSHpZPqx", 42 "2oueNTj4dUE2FFtGyPpawnmCCsy6EUQeVHVLZy8NHeQmkAciP4", 43 "Nzs93kFTvcXanFUp9Y8VQkKYnzmH8xykxVNFJTkdyAEeuxWbP", 44 "2YHZ1KymFjiBhpXzgt6HXJhLSt5SV9UQ4tJuUNjfN1nQQdm5zz", 45 "Qv5v5Ru8ArfnWKB1w6s4G5EYPh7TybHJtF6UsVwAkfvZFoqmj", 46 "z3BgePPpCXq1mRBRvUi28rYYxnEtJizkUEHnDBrcZeVA7MFVk", 47 "Ry2sfjFfGEnJxRkUGFSyZNn7GR3m4aKAf1scDW2uXSNQB568Y", 48 "2YgxGHns7Z2hMMHJsPCgVXuJaL7x1b3gnHbmSCfCdyAcYGr6mx", 49 "cwJusfmn98TW3DjAbfLRN9utYR24KAQ82qpAXmVSvjHyJZuM2", 50 "2JbuExUGKW5mYz5KfXATwq1ibRDimgks9wEdYGNSC6Ttey1R4U", 51 "21Jys8UNURmtckKSV89S2hntEWymJszrLQbdLaNcbXcxDAsQSa", 52 "MjExz2z1qhwugc1tAyiGxRsCq4GvJwKfyyS29nr4tRVB8ooic", 53 "9oZh4qyBCcVwSGyDoUzRAuausvPJN3xH6nopKS6bwYzMfLoQ2", 54 "uK5Ff9iBfDtREpVv9NgCQ1STD1nzLJG3yrfibHG4mGvmybw6f", 55 "22ck2Z7cC38hmBfX2v3jMWxun8eD8psNaicfYeokS67DxwmPTx", 56 "2AfTQ2FXNj9bkSUQnud9pFXULx6EbF7cbbw6i3ayvc2QNhgxfF", 57 "pTf7gfk1ksj7bqMrLyMCij8FBKth1uRqQrtfykMFeXhx5xnrL", 58 "2AXxT3PSEnaYHNtBTnYrVTf24TtKDWjky9sqoFEhydrGXE9iKH", 59 "PJTkRrHvKZ1m4AQdPND1MBpUXpCrGN4DDmXmJQAiUrsxPoLQX", 60 "fV8k1U8oQDmfVwK66kAwN73aSsWiWhm8quNpVnKmSznBycV2W", 61 "sg6wAwFBsPQiS5Yfyh41cVkCRQbrrXsxXmeNyQ1xkunf2sdyv", 62 "soPweZ8DGaoUMjrnzjH3V2bypa7ZvvfqBan4UCsMUxMP759gw", 63 "2dNkpQF4mooveyUDfBYQTBfsGDV4wkncQPpEw4kHKfSTSTo5x", 64 "63YLdYXfXc5tY3mwWLaDsbXzQHYmwWVxMP7HKbRh4Du3C2iM1", 65 "2tCe88ur6MLQcVgwE5XxoaHiTGtSrthwKN3SdbHE4kWiQ7MSTV", 66 "2nG4exd9eUoAGzELfksmBR8XDCKhohY1uDKRFzEXJG4M8p3qA7", 67 "2F5tSQbdTfhZxvkxZqdFp7KR3FrJPKEsDLQK7KtPhNXj1EZAh4", 68 "21o2fVTnzzmtgXqkV1yuQeze7YEQhR5JB31jVVD9oVUnaaV8qm", 69 "2pSjfo7rkFCfZ2CqAxqfw8vqM2CU2nVLHrFZe3rwxz43gkVuGo", 70 "2QBNMMFJmhVHaGF45GAPszKyj1gK6ToBERRxYvXtM7yfrdUGPK", 71 "2ez4CA7w4HHr8SSobHQUAwFgj2giRNjNFUZK9JvrZFa1AuRj6X", 72 "2DpCuBaH94zKKFNY2XTs4GeJcwsEv6qT2DHc59S8tdg97GZpcJ", 73 "i1HoerJ1axognkUKKL58FvF9aLrbZKtv7TdKLkT5kgzoeU1vB", 74 "2SiSziHHqPjb1qkw7CdGYupokiYpd2b7mMqRiyszurctcA5AKr", 75 "esx5J962LtYm2aSrskpLai5e4CMMsaS1dsu9iuLGJ3KWgSu2M", 76 "2czmtnBS44VCWNRFUM89h4Fe9m3ZeZVYyh7Pe3FhNqjRNgPXhZ", 77 "DK9NqAJGry1wAo767uuYc1dYXAjUhzwka6vi8d9tNheqzGUTd", 78 "pE93VXY3N5QKfwsEFcM9i59UpPFgeZ8nxpJNaGaDQyDgsscNf", 79 "AfWvJH3rB2fdHuPWQp6qYNCFVT29MooQPRigD88rKKwUDEDhq", 80 "2KPW9G5tiNF14tZNfG4SqHuQrtUYVZyxuof37aZ7AnTKrQdsHn", 81 "BYqLB6xpqy7HsAgP2XNfGE8Ubg1uEzse5mBPTSJH9z5s8pvMa", 82 "Njm9TcLUXRojZk8YhEM6ksvfiPdC1TME4zJvGaDXgzMCyB6oB", 83 } 84 for _, blkIDStr := range blockIDStrs { 85 blkID, err := ids.FromString(blkIDStr) 86 if err != nil { 87 panic(err) 88 } 89 bonusBlocks.Add(blkID) 90 } 91 } 92 93 // Block implements the snowman.Block interface 94 type Block struct { 95 id ids.ID 96 ethBlock *types.Block 97 vm *VM 98 status choices.Status 99 } 100 101 // ID implements the snowman.Block interface 102 func (b *Block) ID() ids.ID { return b.id } 103 104 // Accept implements the snowman.Block interface 105 func (b *Block) Accept() error { 106 vm := b.vm 107 108 // Although returning an error from Accept is considered fatal, it is good 109 // practice to cleanup the batch we were modifying in the case of an error. 110 defer vm.db.Abort() 111 112 b.status = choices.Accepted 113 log.Debug(fmt.Sprintf("Accepting block %s (%s) at height %d", b.ID().Hex(), b.ID(), b.Height())) 114 if err := vm.chain.Accept(b.ethBlock); err != nil { 115 return fmt.Errorf("chain could not accept %s: %w", b.ID(), err) 116 } 117 if err := vm.acceptedBlockDB.Put(lastAcceptedKey, b.id[:]); err != nil { 118 return fmt.Errorf("failed to put %s as the last accepted block: %w", b.ID(), err) 119 } 120 121 tx, err := vm.extractAtomicTx(b.ethBlock) 122 if err != nil { 123 return err 124 } 125 if tx == nil { 126 return vm.db.Commit() 127 } 128 129 // Remove the accepted transaction from the mempool 130 vm.mempool.RemoveTx(tx.ID()) 131 132 // Save the accepted atomic transaction 133 if err := vm.writeAtomicTx(b, tx); err != nil { 134 return err 135 } 136 137 if bonusBlocks.Contains(b.id) { 138 log.Info("skipping atomic tx acceptance on bonus block", "block", b.id) 139 return vm.db.Commit() 140 } 141 142 batch, err := vm.db.CommitBatch() 143 if err != nil { 144 return fmt.Errorf("failed to create commit batch due to: %w", err) 145 } 146 147 return tx.UnsignedAtomicTx.Accept(vm.ctx, batch) 148 } 149 150 // Reject implements the snowman.Block interface 151 // If [b] contains an atomic transaction, attempt to re-issue it 152 func (b *Block) Reject() error { 153 b.status = choices.Rejected 154 log.Debug(fmt.Sprintf("Rejecting block %s (%s) at height %d", b.ID().Hex(), b.ID(), b.Height())) 155 tx, _ := b.vm.extractAtomicTx(b.ethBlock) 156 if tx != nil { 157 b.vm.mempool.RejectTx(tx.ID()) 158 } 159 160 return b.vm.chain.Reject(b.ethBlock) 161 } 162 163 // SetStatus implements the InternalBlock interface allowing ChainState 164 // to set the status on an existing block 165 func (b *Block) SetStatus(status choices.Status) { b.status = status } 166 167 // Status implements the snowman.Block interface 168 func (b *Block) Status() choices.Status { 169 return b.status 170 } 171 172 // Parent implements the snowman.Block interface 173 func (b *Block) Parent() ids.ID { 174 return ids.ID(b.ethBlock.ParentHash()) 175 } 176 177 // Height implements the snowman.Block interface 178 func (b *Block) Height() uint64 { 179 return b.ethBlock.Number().Uint64() 180 } 181 182 // Timestamp implements the snowman.Block interface 183 func (b *Block) Timestamp() time.Time { 184 return time.Unix(int64(b.ethBlock.Time()), 0) 185 } 186 187 // syntacticVerify verifies that a *Block is well-formed. 188 func (b *Block) syntacticVerify() (params.Rules, error) { 189 if b == nil || b.ethBlock == nil { 190 return params.Rules{}, errInvalidBlock 191 } 192 193 header := b.ethBlock.Header() 194 rules := b.vm.chainConfig.AvalancheRules(header.Number, new(big.Int).SetUint64(header.Time)) 195 return rules, b.vm.getBlockValidator(rules).SyntacticVerify(b) 196 } 197 198 // Verify implements the snowman.Block interface 199 func (b *Block) Verify() error { 200 return b.verify(true) 201 } 202 203 func (b *Block) verify(writes bool) error { 204 rules, err := b.syntacticVerify() 205 if err != nil { 206 return fmt.Errorf("syntactic block verification failed: %w", err) 207 } 208 209 vm := b.vm 210 211 // Ensure that the parent was verified and inserted correctly. 212 ancestorID := b.Parent() 213 ancestorHash := common.Hash(ancestorID) 214 if !vm.chain.BlockChain().HasBlock(ancestorHash, b.Height()-1) { 215 return errRejectedParent 216 } 217 218 // If the tx is an atomic tx, ensure that it doesn't conflict with any of 219 // its processing ancestry. 220 atomicTx, err := vm.extractAtomicTx(b.ethBlock) 221 if err != nil { 222 return err 223 } 224 if atomicTx != nil { 225 // If the ancestor is unknown, then the parent failed verification when 226 // it was called. 227 // If the ancestor is rejected, then this block shouldn't be inserted 228 // into the canonical chain because the parent is will be missing. 229 ancestorInf, err := vm.GetBlockInternal(ancestorID) 230 if err != nil { 231 return errRejectedParent 232 } 233 234 if blkStatus := ancestorInf.Status(); blkStatus == choices.Unknown || blkStatus == choices.Rejected { 235 return errRejectedParent 236 } 237 ancestor, ok := ancestorInf.(*Block) 238 if !ok { 239 return fmt.Errorf("expected %s, parent of %s, to be *Block but is %T", ancestor.ID(), b.ID(), ancestorInf) 240 } 241 242 if bonusBlocks.Contains(b.id) { 243 log.Info("skipping atomic tx verification on bonus block", "block", b.id) 244 } else { 245 utx := atomicTx.UnsignedAtomicTx 246 if err := utx.SemanticVerify(vm, atomicTx, ancestor, b.ethBlock.BaseFee(), rules); err != nil { 247 return fmt.Errorf("invalid block due to failed semanatic verify: %w at height %d", err, b.Height()) 248 } 249 } 250 } 251 252 bc := vm.chain.BlockChain() 253 return bc.InsertBlockManual(b.ethBlock, writes) 254 } 255 256 // Bytes implements the snowman.Block interface 257 func (b *Block) Bytes() []byte { 258 res, err := rlp.EncodeToBytes(b.ethBlock) 259 if err != nil { 260 panic(err) 261 } 262 return res 263 } 264 265 func (b *Block) String() string { return fmt.Sprintf("EVM block, ID = %s", b.ID()) }