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  }