github.com/amazechain/amc@v0.1.3/cmd/verify/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 main 18 19 import ( 20 "context" 21 "fmt" 22 common2 "github.com/amazechain/amc/common" 23 block2 "github.com/amazechain/amc/common/block" 24 "github.com/amazechain/amc/common/transaction" 25 "github.com/amazechain/amc/common/types" 26 "github.com/amazechain/amc/internal" 27 "github.com/amazechain/amc/internal/consensus/apos" 28 "github.com/amazechain/amc/internal/consensus/misc" 29 "github.com/amazechain/amc/internal/vm" 30 "github.com/amazechain/amc/modules/ethdb/olddb" 31 "github.com/amazechain/amc/modules/state" 32 "github.com/amazechain/amc/params" 33 "unsafe" 34 ) 35 36 func verify(ctx context.Context, msg *state.EntireCode) types.Hash { 37 codeMap := make(map[types.Hash][]byte) 38 for _, pair := range msg.Codes { 39 codeMap[pair.Hash] = pair.Code 40 } 41 42 readCodeF := func(hash types.Hash) ([]byte, error) { 43 if code, ok := codeMap[hash]; ok { 44 return code, nil 45 } 46 return nil, nil 47 } 48 49 hashMap := make(map[uint64]types.Hash) 50 for _, h := range msg.Headers { 51 hashMap[h.Number.Uint64()] = h.Hash() 52 } 53 getNumberHash := func(n uint64) types.Hash { 54 if hash, ok := hashMap[n]; ok { 55 return hash 56 } 57 return types.Hash{} 58 } 59 60 var txs transaction.Transactions 61 for _, tByte := range msg.Entire.Transactions { 62 tmp := &transaction.Transaction{} 63 if err := tmp.Unmarshal(tByte); nil != err { 64 panic(err) 65 } 66 txs = append(txs, tmp) 67 } 68 69 body := &block2.Body{ 70 Txs: txs, 71 } 72 73 block := block2.NewBlockFromStorage(msg.Entire.Header.Hash(), msg.Entire.Header, body) 74 batch := olddb.NewHashBatch(nil, ctx.Done(), "") 75 defer batch.Rollback() 76 old := make(map[string][]byte, len(msg.Entire.Snap.Items)) 77 for _, v := range msg.Entire.Snap.Items { 78 old[*(*string)(unsafe.Pointer(&v.Key))] = v.Value 79 } 80 stateReader := olddb.NewStateReader(old, nil, batch, block.Number64().Uint64()) 81 stateReader.SetReadCodeF(readCodeF) 82 ibs := state.New(stateReader) 83 ibs.SetSnapshot(msg.Entire.Snap) 84 ibs.SetHeight(block.Number64().Uint64()) 85 ibs.SetGetOneFun(batch.GetOne) 86 87 root, err := checkBlock(getNumberHash, block, ibs, msg.CoinBase, msg.Rewards) 88 if nil != err { 89 panic(err) 90 } 91 return root 92 } 93 94 func checkBlock(getHashF func(n uint64) types.Hash, block *block2.Block, ibs *state.IntraBlockState, coinbase types.Address, rewards []*block2.Reward) (types.Hash, error) { 95 header := block.Header().(*block2.Header) 96 chainConfig := params.MainnetChainConfig 97 if chainConfig.DAOForkSupport && chainConfig.DAOForkBlock != nil && chainConfig.DAOForkBlock.Cmp(block.Number64().ToBig()) == 0 { 98 misc.ApplyDAOHardFork(ibs) 99 } 100 noop := state.NewNoopWriter() 101 102 usedGas := new(uint64) 103 gp := new(common2.GasPool) 104 gp.AddGas(block.GasLimit()) 105 cfg := vm.Config{} 106 //cfg := vm.Config{Debug: true, Tracer: logger.NewMarkdownLogger(nil, os.Stdout)} 107 108 engine := apos.NewFaker() 109 for i, tx := range block.Transactions() { 110 ibs.Prepare(tx.Hash(), block.Hash(), i) 111 _, _, err := internal.ApplyTransaction(chainConfig, getHashF, engine, &coinbase, gp, ibs, noop, header, tx, usedGas, cfg) 112 if err != nil { 113 114 return types.Hash{}, err 115 } 116 } 117 118 if !cfg.StatelessExec && *usedGas != header.GasUsed { 119 return types.Hash{}, fmt.Errorf("gas used by execution: %d, in header: %d", *usedGas, header.GasUsed) 120 } 121 122 if len(rewards) > 0 { 123 for _, reward := range rewards { 124 if reward.Amount != nil && !reward.Amount.IsZero() { 125 if !ibs.Exist(reward.Address) { 126 ibs.CreateAccount(reward.Address, false) 127 } 128 ibs.AddBalance(reward.Address, reward.Amount) 129 } 130 } 131 ibs.SoftFinalise() 132 } 133 134 return ibs.IntermediateRoot(), nil 135 }