github.com/amazechain/amc@v0.1.3/cmd/evmsdk/verify.go (about) 1 // Copyright 2023 The AmazeChain Authors 2 // This file is part of the AmazeChain library. 3 // 4 // The AmazeChain library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The AmazeChain library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the AmazeChain library. If not, see <http://www.gnu.org/licenses/>. 16 17 package evmsdk 18 19 import ( 20 "context" 21 "fmt" 22 "unsafe" 23 24 common2 "github.com/amazechain/amc/common" 25 block2 "github.com/amazechain/amc/common/block" 26 "github.com/amazechain/amc/common/transaction" 27 "github.com/amazechain/amc/common/types" 28 "github.com/amazechain/amc/internal" 29 "github.com/amazechain/amc/internal/consensus/apos" 30 "github.com/amazechain/amc/internal/consensus/misc" 31 "github.com/amazechain/amc/internal/vm" 32 "github.com/amazechain/amc/modules/ethdb/olddb" 33 "github.com/amazechain/amc/modules/state" 34 "github.com/amazechain/amc/params" 35 ) 36 37 func verify(ctx context.Context, msg *state.EntireCode) types.Hash { 38 codeMap := make(map[types.Hash][]byte) 39 for _, pair := range msg.Codes { 40 codeMap[pair.Hash] = pair.Code 41 } 42 43 readCodeF := func(hash types.Hash) ([]byte, error) { 44 if code, ok := codeMap[hash]; ok { 45 return code, nil 46 } 47 return nil, nil 48 } 49 50 hashMap := make(map[uint64]types.Hash) 51 for _, h := range msg.Headers { 52 hashMap[h.Number.Uint64()] = h.Hash() 53 } 54 getNumberHash := func(n uint64) types.Hash { 55 if hash, ok := hashMap[n]; ok { 56 return hash 57 } 58 return types.Hash{} 59 } 60 61 var txs transaction.Transactions 62 for _, tByte := range msg.Entire.Transactions { 63 tmp := &transaction.Transaction{} 64 if err := tmp.Unmarshal(tByte); nil != err { 65 panic(err) 66 } 67 txs = append(txs, tmp) 68 } 69 70 body := &block2.Body{ 71 Txs: txs, 72 } 73 74 block := block2.NewBlockFromStorage(msg.Entire.Header.Hash(), msg.Entire.Header, body) 75 batch := olddb.NewHashBatch(nil, ctx.Done(), "") 76 defer batch.Rollback() 77 old := make(map[string][]byte, len(msg.Entire.Snap.Items)) 78 for _, v := range msg.Entire.Snap.Items { 79 old[*(*string)(unsafe.Pointer(&v.Key))] = v.Value 80 } 81 stateReader := olddb.NewStateReader(old, nil, batch, block.Number64().Uint64()) 82 stateReader.SetReadCodeF(readCodeF) 83 ibs := state.New(stateReader) 84 ibs.SetSnapshot(msg.Entire.Snap) 85 ibs.SetHeight(block.Number64().Uint64()) 86 ibs.SetGetOneFun(batch.GetOne) 87 88 root, err := checkBlock2(getNumberHash, block, ibs, msg.CoinBase, msg.Rewards) 89 if nil != err { 90 panic(err) 91 } 92 return root 93 } 94 95 func checkBlock2(getHashF func(n uint64) types.Hash, block *block2.Block, ibs *state.IntraBlockState, coinbase types.Address, rewards []*block2.Reward) (types.Hash, error) { 96 header := block.Header().(*block2.Header) 97 chainConfig := params.MainnetChainConfig 98 if chainConfig.DAOForkSupport && chainConfig.DAOForkBlock != nil && chainConfig.DAOForkBlock.Cmp(block.Number64().ToBig()) == 0 { 99 misc.ApplyDAOHardFork(ibs) 100 } 101 noop := state.NewNoopWriter() 102 103 usedGas := new(uint64) 104 gp := new(common2.GasPool) 105 gp.AddGas(block.GasLimit()) 106 cfg := vm.Config{} 107 //cfg := vm.Config{Debug: true, Tracer: logger.NewMarkdownLogger(nil, os.Stdout)} 108 109 engine := apos.NewFaker() 110 for i, tx := range block.Transactions() { 111 ibs.Prepare(tx.Hash(), block.Hash(), i) 112 _, _, err := internal.ApplyTransaction(chainConfig, getHashF, engine, &coinbase, gp, ibs, noop, header, tx, usedGas, cfg) 113 if err != nil { 114 115 return types.Hash{}, err 116 } 117 } 118 119 if !cfg.StatelessExec && *usedGas != header.GasUsed { 120 return types.Hash{}, fmt.Errorf("gas used by execution: %d, in header: %d", *usedGas, header.GasUsed) 121 } 122 123 if len(rewards) > 0 { 124 for _, reward := range rewards { 125 if reward.Amount != nil && !reward.Amount.IsZero() { 126 if !ibs.Exist(reward.Address) { 127 ibs.CreateAccount(reward.Address, false) 128 } 129 ibs.AddBalance(reward.Address, reward.Amount) 130 } 131 } 132 ibs.SoftFinalise() 133 } 134 135 return ibs.IntermediateRoot(), nil 136 }