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  }