Merge pull request #296 from XinFinOrg/dev-upgrade-merge-master

Dev upgrade merge master
This commit is contained in:
Liam 2023-08-02 17:29:48 +10:00 committed by GitHub
commit bb6d797dad
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
30 changed files with 376 additions and 86 deletions

2
.gitignore vendored
View file

@ -54,4 +54,4 @@ go.sum
cicd/devnet/terraform/.terraform
cicd/devnet/.pwd
cicd/devnet/tmp/
cicd/devnet/tmp/

View file

@ -24,15 +24,6 @@ env:
jobs:
include:
# TODO: temporary turn off linting to help fix all the tests. We will turn it back on once the branch is stable
# - stage: Lint
# sudo: false
# go: '1.14.x'
# git:
# submodules: false
# script:
# - go run build/ci.go lint
- stage: Tests
os: linux
dist: bionic

View file

@ -1,4 +1,15 @@
# XDPoSChain
<p align="center">
<img src="./assets/images/xinfin-logo.png" />
</p>
<p align="center">
XinFin XDPoSchain<br/>
Enterprise ready hybrid blockchain for global trade and finance
</p>
<br/>
## XinFin Hybrid Blockchain
XinFin Hybrid Blockchain is an Enterprise ready Blockchain for global trade and finance
@ -51,5 +62,4 @@ See https://github.com/XinFinOrg/XDPoSChain/tree/dev-upgrade/cicd
Simple create a pull request along with proper reasoning, we'll get back to you.
Our Channels : [Telegram Developer Group](https://t.me/XinFinDevelopers) or [Public Slack Group](https://launchpass.com/xinfin-public)
Our Channels : [Telegram Developer Group](https://t.me/XinFinDevelopers) or [XDC.Dev](https://xdc.dev)

View file

@ -10,7 +10,7 @@ import (
)
var (
EmptyAddress = "0x0000000000000000000000000000000000000000"
EmptyAddress = "xdc0000000000000000000000000000000000000000"
EmptyRoot = common.HexToHash("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421")
)

View file

@ -19,8 +19,11 @@ package abi
import (
"bytes"
"encoding/json"
"errors"
"fmt"
"io"
"github.com/XinFinOrg/XDPoSChain/crypto"
)
// The ABI holds information about a contract's context and available
@ -144,3 +147,26 @@ func (abi *ABI) MethodById(sigdata []byte) (*Method, error) {
}
return nil, fmt.Errorf("no method with id: %#x", sigdata[:4])
}
// revertSelector is a special function selector for revert reason unpacking.
var revertSelector = crypto.Keccak256([]byte("Error(string)"))[:4]
// UnpackRevert resolves the abi-encoded revert reason. According to the solidity
// spec https://solidity.readthedocs.io/en/latest/control-structures.html#revert,
// the provided revert reason is abi-encoded as if it were a call to a function
// `Error(string)`. So it's a special tool for it.
func UnpackRevert(data []byte) (string, error) {
if len(data) < 4 {
return "", errors.New("invalid data for unpacking")
}
if !bytes.Equal(data[:4], revertSelector) {
return "", errors.New("invalid data for unpacking")
}
typ, _ := NewType("string")
unpacked, err := (Arguments{{Type: typ}}).Unpack2(data[4:])
if err != nil {
return "", err
}
return unpacked[0].(string), nil
}

View file

@ -18,6 +18,7 @@ package abi
import (
"encoding/json"
"errors"
"fmt"
"reflect"
"strings"
@ -100,6 +101,17 @@ func (arguments Arguments) Unpack(v interface{}, data []byte) error {
return arguments.unpackAtomic(v, marshalledValues)
}
// Unpack2 performs the operation hexdata -> Go format.
func (arguments Arguments) Unpack2(data []byte) ([]interface{}, error) {
if len(data) == 0 {
if len(arguments.NonIndexed()) != 0 {
return nil, errors.New("abi: attempting to unmarshall an empty string while arguments are expected")
}
return make([]interface{}, 0), nil
}
return arguments.UnpackValues(data)
}
func (arguments Arguments) unpackTuple(v interface{}, marshalledValues []interface{}) error {
var (

View file

@ -351,7 +351,7 @@ func (b *SimulatedBackend) EstimateGas(ctx context.Context, call XDPoSChain.Call
// callContract implements common code between normal and pending contract calls.
// state is modified during execution, make sure to copy it if necessary.
func (b *SimulatedBackend) callContract(ctx context.Context, call XDPoSChain.CallMsg, block *types.Block, statedb *state.StateDB) ([]byte, uint64, bool, error) {
func (b *SimulatedBackend) callContract(ctx context.Context, call XDPoSChain.CallMsg, block *types.Block, statedb *state.StateDB) (ret []byte, usedGas uint64, failed bool, err error) {
// Ensure message is initialized properly.
if call.GasPrice == nil {
call.GasPrice = big.NewInt(1)
@ -379,7 +379,8 @@ func (b *SimulatedBackend) callContract(ctx context.Context, call XDPoSChain.Cal
vmenv := vm.NewEVM(evmContext, statedb, nil, b.config, vm.Config{})
gaspool := new(core.GasPool).AddGas(math.MaxUint64)
owner := common.Address{}
return core.NewStateTransition(vmenv, msg, gaspool).TransitionDb(owner)
ret, usedGas, failed, err, _ = core.NewStateTransition(vmenv, msg, gaspool).TransitionDb(owner)
return
}
// SendTransaction updates the pending block to include the given transaction.

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

143
cmd/XDC/apothem.go Normal file

File diff suppressed because one or more lines are too long

View file

@ -105,5 +105,4 @@ const header = `Please answer these questions before submitting your issue. Than
#### What did you see instead?
#### System details
`
#### System details`

View file

@ -25,18 +25,17 @@ import (
"sync/atomic"
"time"
"github.com/XinFinOrg/XDPoSChain/core/rawdb"
"github.com/XinFinOrg/XDPoSChain/metrics"
"github.com/XinFinOrg/XDPoSChain/cmd/utils"
"github.com/XinFinOrg/XDPoSChain/common"
"github.com/XinFinOrg/XDPoSChain/console"
"github.com/XinFinOrg/XDPoSChain/core"
"github.com/XinFinOrg/XDPoSChain/core/rawdb"
"github.com/XinFinOrg/XDPoSChain/core/state"
"github.com/XinFinOrg/XDPoSChain/core/types"
"github.com/XinFinOrg/XDPoSChain/eth/downloader"
"github.com/XinFinOrg/XDPoSChain/event"
"github.com/XinFinOrg/XDPoSChain/log"
"github.com/XinFinOrg/XDPoSChain/metrics"
"gopkg.in/urfave/cli.v1"
)
@ -49,6 +48,7 @@ var (
Flags: []cli.Flag{
utils.DataDirFlag,
utils.LightModeFlag,
utils.XDCTestnetFlag,
},
Category: "BLOCKCHAIN COMMANDS",
Description: `
@ -176,19 +176,31 @@ Use "ethereum dump 0" to dump the genesis block.`,
func initGenesis(ctx *cli.Context) error {
// Make sure we have a valid genesis JSON
genesisPath := ctx.Args().First()
if len(genesisPath) == 0 {
utils.Fatalf("Must supply path to genesis JSON file")
}
file, err := os.Open(genesisPath)
if err != nil {
utils.Fatalf("Failed to read genesis file: %v", err)
}
defer file.Close()
genesis := new(core.Genesis)
if err := json.NewDecoder(file).Decode(genesis); err != nil {
utils.Fatalf("invalid genesis file: %v", err)
if ctx.GlobalBool(utils.XDCTestnetFlag.Name) {
if len(genesisPath) > 0 {
utils.Fatalf("Flags --apothem and genesis file can't be used at the same time")
}
err := json.Unmarshal(apothemGenesis, &genesis)
if err != nil {
utils.Fatalf("invalid genesis json: %v", err)
}
} else {
if len(genesisPath) == 0 {
utils.Fatalf("Must supply path to genesis JSON file")
}
file, err := os.Open(genesisPath)
if err != nil {
utils.Fatalf("Failed to read genesis file: %v", err)
}
defer file.Close()
if err := json.NewDecoder(file).Decode(genesis); err != nil {
utils.Fatalf("invalid genesis file: %v", err)
}
}
// Open an initialise both full and light databases
stack, _ := makeFullNode(ctx)
for _, name := range []string{"chaindata", "lightchaindata"} {

View file

@ -160,11 +160,14 @@ func makeConfigNode(ctx *cli.Context) (*node.Node, XDCConfig) {
common.TRC21IssuerSMC = common.TRC21IssuerSMCTestNet
cfg.Eth.NetworkId = 51
common.RelayerRegistrationSMC = common.RelayerRegistrationSMCTestnet
common.TIPTRC21Fee = common.TIPXDCXTestnet
common.TIPTRC21Fee = common.TIPTRC21FeeTestnet
common.TIPXDCXCancellationFee = common.TIPXDCXCancellationFeeTestnet
}
if ctx.GlobalBool(utils.Enable0xPrefixFlag.Name) {
common.Enable0xPrefix = true
}
// Rewound
if rewound := ctx.GlobalInt(utils.RewoundFlag.Name); rewound != 0 {
common.Rewound = uint64(rewound)

View file

@ -113,6 +113,7 @@ var (
//utils.RinkebyFlag,
//utils.VMEnableDebugFlag,
utils.XDCTestnetFlag,
utils.Enable0xPrefixFlag,
utils.RewoundFlag,
utils.NetworkIdFlag,
utils.RPCCORSDomainFlag,

View file

@ -116,6 +116,10 @@ var (
Usage: "Rollback chain at hash",
Value: "",
}
Enable0xPrefixFlag = cli.BoolFlag{
Name: "enable-0x-prefix",
Usage: "Addres use 0x-prefix (default = false)",
}
// General settings
AnnounceTxsFlag = cli.BoolFlag{
Name: "announce-txs",

View file

@ -48,6 +48,7 @@ var TIPXDCXCancellationFeeTestnet = big.NewInt(38383838)
var TIPXDCXTestnet = big.NewInt(38383838)
var IsTestnet bool = false
var Enable0xPrefix bool = false
var StoreRewardFolder string
var RollbackHash Hash
var BasePrice = big.NewInt(1000000000000000000) // 1

View file

@ -250,8 +250,11 @@ func (a *Address) Set(other Address) {
// MarshalText returns the hex representation of a.
func (a Address) MarshalText() ([]byte, error) {
// Handle '0x' or 'xdc' prefix here.
// return hexutil.Bytes(a[:]).MarshalText()
return hexutil.Bytes(a[:]).MarshalXDCText()
if (Enable0xPrefix) {
return hexutil.Bytes(a[:]).MarshalText()
} else {
return hexutil.Bytes(a[:]).MarshalXDCText()
}
}
// UnmarshalText parses a hash in hex syntax.

View file

@ -57,7 +57,7 @@ func (x *XDPoS_v2) getEpochSwitchInfo(chain consensus.ChainReader, header *types
return nil, err
}
snap, err := x.getSnapshot(chain, header.Number.Uint64(), false)
snap, err := x.getSnapshot(chain, h.Number.Uint64(), false)
if err != nil {
log.Error("[getEpochSwitchInfo] Adaptor v2 getSnapshot has error", "err", err)
return nil, err

View file

@ -184,6 +184,7 @@ func TestAdaptorGetMasternodesV2(t *testing.T) {
// block 901 is the first v2 block, and is treated as epoch switch block
err := blockchain.InsertBlock(currentBlock)
adaptor.Initial(blockchain, currentBlock.Header())
assert.Nil(t, err)
masternodes1 := adaptor.GetMasternodes(blockchain, currentBlock.Header())
assert.Equal(t, 5, len(masternodes1))
@ -216,6 +217,8 @@ func TestGetCurrentEpochSwitchBlock(t *testing.T) {
currentBlock = CreateBlock(blockchain, params.TestXDPoSMockChainConfig, currentBlock, blockNum, 1, blockCoinBase, signer, signFn, nil, nil, "")
err = blockchain.InsertBlock(currentBlock)
assert.Nil(t, err)
adaptor.Initial(blockchain, currentBlock.Header())
currentCheckpointNumber, epochNum, err = adaptor.GetCurrentEpochSwitchBlock(blockchain, currentBlock.Number())
assert.Nil(t, err)
assert.Equal(t, uint64(901), currentCheckpointNumber)

View file

@ -43,6 +43,8 @@ func TestIsYourTurnConsensusV2(t *testing.T) {
currentBlockHeader.Time = big.NewInt(time.Now().Unix())
err := blockchain.InsertBlock(currentBlock)
assert.Nil(t, err)
adaptor.Initial(blockchain, currentBlockHeader)
// Less then Mine Period
isYourTurn, err := adaptor.YourTurn(blockchain, currentBlockHeader, common.HexToAddress("xdc0D3ab14BBaD3D99F4203bd7a11aCB94882050E7e"))
assert.Nil(t, err)

View file

@ -409,7 +409,7 @@ func ApplyTransaction(config *params.ChainConfig, tokensFee map[common.Address]*
// End Bypass blacklist address
// Apply the transaction to the current state (included in the env)
_, gas, failed, err := ApplyMessage(vmenv, msg, gp, coinbaseOwner)
_, gas, failed, err, _ := ApplyMessage(vmenv, msg, gp, coinbaseOwner)
if err != nil {
return nil, 0, err, false

View file

@ -129,7 +129,7 @@ func NewStateTransition(evm *vm.EVM, msg Message, gp *GasPool) *StateTransition
// the gas used (which includes gas refunds) and an error if it failed. An error always
// indicates a core error meaning that the message would always fail for that particular
// state and would never be accepted within a block.
func ApplyMessage(evm *vm.EVM, msg Message, gp *GasPool, owner common.Address) ([]byte, uint64, bool, error) {
func ApplyMessage(evm *vm.EVM, msg Message, gp *GasPool, owner common.Address) ([]byte, uint64, bool, error, error) {
return NewStateTransition(evm, msg, gp).TransitionDb(owner)
}
@ -215,7 +215,7 @@ func (st *StateTransition) preCheck() error {
// TransitionDb will transition the state by applying the current message and
// returning the result including the the used gas. It returns an error if it
// failed. An error indicates a consensus issue.
func (st *StateTransition) TransitionDb(owner common.Address) (ret []byte, usedGas uint64, failed bool, err error) {
func (st *StateTransition) TransitionDb(owner common.Address) (ret []byte, usedGas uint64, failed bool, err error, vmErr error) {
if err = st.preCheck(); err != nil {
return
}
@ -228,10 +228,10 @@ func (st *StateTransition) TransitionDb(owner common.Address) (ret []byte, usedG
// Pay intrinsic gas
gas, err := IntrinsicGas(st.data, contractCreation, homestead)
if err != nil {
return nil, 0, false, err
return nil, 0, false, err, nil
}
if err = st.useGas(gas); err != nil {
return nil, 0, false, err
return nil, 0, false, err, nil
}
var (
@ -261,7 +261,7 @@ func (st *StateTransition) TransitionDb(owner common.Address) (ret []byte, usedG
// sufficient balance to make the transfer happen. The first
// balance transfer may never fail.
if vmerr == vm.ErrInsufficientBalance {
return nil, 0, false, vmerr
return nil, 0, false, vmerr, nil
}
}
st.refundGas()
@ -274,7 +274,7 @@ func (st *StateTransition) TransitionDb(owner common.Address) (ret []byte, usedG
st.state.AddBalance(st.evm.Coinbase, new(big.Int).Mul(new(big.Int).SetUint64(st.gasUsed()), st.gasPrice))
}
return ret, st.gasUsed(), vmerr != nil, err
return ret, st.gasUsed(), vmerr != nil, err, vmerr
}
func (st *StateTransition) refundGas() {

View file

@ -112,7 +112,7 @@ func CallContractWithState(call ethereum.CallMsg, chain consensus.ChainContext,
vmenv := vm.NewEVM(evmContext, statedb, nil, chain.Config(), vm.Config{})
gaspool := new(GasPool).AddGas(1000000)
owner := common.Address{}
rval, _, _, err := NewStateTransition(vmenv, msg, gaspool).TransitionDb(owner)
rval, _, _, err, _ := NewStateTransition(vmenv, msg, gaspool).TransitionDb(owner)
if err != nil {
return nil, err
}

View file

@ -726,3 +726,5 @@ func (m Message) Gas() uint64 { return m.gasLimit }
func (m Message) Nonce() uint64 { return m.nonce }
func (m Message) Data() []byte { return m.data }
func (m Message) CheckNonce() bool { return m.checkNonce }
func (m *Message) SetNonce(nonce uint64) { m.nonce = nonce }

View file

@ -474,11 +474,13 @@ func (api *PrivateDebugAPI) traceBlock(ctx context.Context, block *types.Block,
}
// Generate the next state snapshot fast without tracing
msg, _ := tx.AsMessage(signer, balacne, block.Number())
// Set nonce to fix issue #256
msg.SetNonce(statedb.GetNonce(*tx.From()))
vmctx := core.NewEVMContext(msg, block.Header(), api.eth.blockchain, nil)
vmenv := vm.NewEVM(vmctx, statedb, XDCxState, api.config, vm.Config{})
owner := common.Address{}
if _, _, _, err := core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(msg.Gas()), owner); err != nil {
if _, _, _, err, _ := core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(msg.Gas()), owner); err != nil {
failed = err
break
}
@ -634,7 +636,7 @@ func (api *PrivateDebugAPI) traceTx(ctx context.Context, message core.Message, v
vmenv := vm.NewEVM(vmctx, statedb, nil, api.config, vm.Config{Debug: true, Tracer: tracer})
owner := common.Address{}
ret, gas, failed, err := core.ApplyMessage(vmenv, message, new(core.GasPool).AddGas(message.Gas()), owner)
ret, gas, failed, err, _ := core.ApplyMessage(vmenv, message, new(core.GasPool).AddGas(message.Gas()), owner)
if err != nil {
return nil, fmt.Errorf("tracing failed: %v", err)
}

View file

@ -238,7 +238,7 @@ func AttachConsensusV1Hooks(adaptor *XDPoS.XDPoS, bc *core.BlockChain, chainConf
if err != nil {
return nil, err
}
if address.String() != "0x0000000000000000000000000000000000000000" {
if address.String() != "xdc0000000000000000000000000000000000000000" {
candidates = append(candidates, utils.Masternode{Address: address, Stake: v})
}
}

View file

@ -20,6 +20,13 @@ import (
"crypto/ecdsa"
"crypto/rand"
"encoding/json"
"io/ioutil"
"math/big"
"path/filepath"
"reflect"
"strings"
"testing"
"github.com/XinFinOrg/XDPoSChain/common"
"github.com/XinFinOrg/XDPoSChain/common/hexutil"
"github.com/XinFinOrg/XDPoSChain/common/math"
@ -31,12 +38,6 @@ import (
"github.com/XinFinOrg/XDPoSChain/params"
"github.com/XinFinOrg/XDPoSChain/rlp"
"github.com/XinFinOrg/XDPoSChain/tests"
"io/ioutil"
"math/big"
"path/filepath"
"reflect"
"strings"
"testing"
)
// To generate a new callTracer test, copy paste the makeTest method below into
@ -183,7 +184,7 @@ func TestPrestateTracerCreate2(t *testing.T) {
t.Fatalf("failed to prepare transaction for tracing: %v", err)
}
st := core.NewStateTransition(evm, msg, new(core.GasPool).AddGas(tx.Gas()))
if _, _, _, err = st.TransitionDb(common.Address{}); err != nil {
if _, _, _, err, _ = st.TransitionDb(common.Address{}); err != nil {
t.Fatalf("failed to execute transaction: %v", err)
}
// Retrieve the trace result and compare against the etalon
@ -258,7 +259,7 @@ func TestCallTracer(t *testing.T) {
t.Fatalf("failed to prepare transaction for tracing: %v", err)
}
st := core.NewStateTransition(evm, msg, new(core.GasPool).AddGas(tx.Gas()))
if _, _, _, err = st.TransitionDb(common.Address{}); err != nil {
if _, _, _, err, _ = st.TransitionDb(common.Address{}); err != nil {
t.Fatalf("failed to execute transaction: %v", err)
}
// Retrieve the trace result and compare against the etalon

View file

@ -26,17 +26,16 @@ import (
"strings"
"time"
"github.com/XinFinOrg/XDPoSChain/XDCxlending/lendingstate"
"github.com/XinFinOrg/XDPoSChain/consensus"
"github.com/XinFinOrg/XDPoSChain/XDCx/tradingstate"
"github.com/XinFinOrg/XDPoSChain/XDCxlending/lendingstate"
"github.com/XinFinOrg/XDPoSChain/accounts"
"github.com/XinFinOrg/XDPoSChain/accounts/abi"
"github.com/XinFinOrg/XDPoSChain/accounts/abi/bind"
"github.com/XinFinOrg/XDPoSChain/accounts/keystore"
"github.com/XinFinOrg/XDPoSChain/common"
"github.com/XinFinOrg/XDPoSChain/common/hexutil"
"github.com/XinFinOrg/XDPoSChain/common/math"
"github.com/XinFinOrg/XDPoSChain/consensus"
"github.com/XinFinOrg/XDPoSChain/consensus/XDPoS"
"github.com/XinFinOrg/XDPoSChain/consensus/XDPoS/utils"
"github.com/XinFinOrg/XDPoSChain/consensus/ethash"
@ -757,7 +756,7 @@ func (s *PublicBlockChainAPI) GetCandidateStatus(ctx context.Context, coinbaseAd
candidatesAddresses := state.GetCandidates(statedb)
for _, address := range candidatesAddresses {
v := state.GetCandidateCap(statedb, address)
if address.String() != "0x0000000000000000000000000000000000000000" {
if address.String() != "xdc0000000000000000000000000000000000000000" {
candidates = append(candidates, utils.Masternode{Address: address, Stake: v})
}
}
@ -883,7 +882,7 @@ func (s *PublicBlockChainAPI) GetCandidates(ctx context.Context, epoch rpc.Epoch
candidatesAddresses := state.GetCandidates(statedb)
for _, address := range candidatesAddresses {
v := state.GetCandidateCap(statedb, address)
if address.String() != "0x0000000000000000000000000000000000000000" {
if address.String() != "xdc0000000000000000000000000000000000000000" {
candidates = append(candidates, utils.Masternode{Address: address, Stake: v})
}
}
@ -1017,7 +1016,7 @@ func (s *PublicBlockChainAPI) getCandidatesFromSmartContract() ([]utils.Masterno
if err != nil {
return []utils.Masternode{}, err
}
if candidate.String() != "0x0000000000000000000000000000000000000000" {
if candidate.String() != "xdc0000000000000000000000000000000000000000" {
candidatesWithStakeInfo = append(candidatesWithStakeInfo, utils.Masternode{Address: candidate, Stake: v})
}
@ -1040,12 +1039,12 @@ type CallArgs struct {
Data hexutil.Bytes `json:"data"`
}
func (s *PublicBlockChainAPI) doCall(ctx context.Context, args CallArgs, blockNr rpc.BlockNumber, vmCfg vm.Config, timeout time.Duration) ([]byte, uint64, bool, error) {
func (s *PublicBlockChainAPI) doCall(ctx context.Context, args CallArgs, blockNr rpc.BlockNumber, vmCfg vm.Config, timeout time.Duration) ([]byte, uint64, bool, error, error) {
defer func(start time.Time) { log.Debug("Executing EVM call finished", "runtime", time.Since(start)) }(time.Now())
statedb, header, err := s.b.StateAndHeaderByNumber(ctx, blockNr)
if statedb == nil || err != nil {
return nil, 0, false, err
return nil, 0, false, err, nil
}
// Set sender address or use a default if none specified
addr := args.From
@ -1083,20 +1082,20 @@ func (s *PublicBlockChainAPI) doCall(ctx context.Context, args CallArgs, blockNr
block, err := s.b.BlockByNumber(ctx, blockNr)
if err != nil {
return nil, 0, false, err
return nil, 0, false, err, nil
}
author, err := s.b.GetEngine().Author(block.Header())
if err != nil {
return nil, 0, false, err
return nil, 0, false, err, nil
}
XDCxState, err := s.b.XDCxService().GetTradingState(block, author)
if err != nil {
return nil, 0, false, err
return nil, 0, false, err, nil
}
// Get a new instance of the EVM.
evm, vmError, err := s.b.GetEVM(ctx, msg, statedb, XDCxState, header, vmCfg)
if err != nil {
return nil, 0, false, err
return nil, 0, false, err, nil
}
// Wait for the context to be done and cancel the evm. Even if the
// EVM has finished, cancelling may be done (repeatedly)
@ -1109,18 +1108,64 @@ func (s *PublicBlockChainAPI) doCall(ctx context.Context, args CallArgs, blockNr
// and apply the message.
gp := new(core.GasPool).AddGas(math.MaxUint64)
owner := common.Address{}
res, gas, failed, err := core.ApplyMessage(evm, msg, gp, owner)
res, gas, failed, err, vmErr := core.ApplyMessage(evm, msg, gp, owner)
if err := vmError(); err != nil {
return nil, 0, false, err
return nil, 0, false, err, nil
}
return res, gas, failed, err
// If the timer caused an abort, return an appropriate error message
if evm.Cancelled() {
return nil, 0, false, fmt.Errorf("execution aborted (timeout = %v)", timeout), nil
}
if err != nil {
return res, 0, false, fmt.Errorf("err: %w (supplied gas %d)", err, msg.Gas()), nil
}
return res, gas, failed, err, vmErr
}
func newRevertError(res []byte) *revertError {
reason, errUnpack := abi.UnpackRevert(res)
err := errors.New("execution reverted")
if errUnpack == nil {
err = fmt.Errorf("execution reverted: %v", reason)
}
return &revertError{
error: err,
reason: hexutil.Encode(res),
}
}
// revertError is an API error that encompasses an EVM revertal with JSON error
// code and a binary data blob.
type revertError struct {
error
reason string // revert reason hex encoded
}
// ErrorCode returns the JSON error code for a revertal.
// See: https://github.com/ethereum/wiki/wiki/JSON-RPC-Error-Codes-Improvement-Proposal
func (e *revertError) ErrorCode() int {
return 3
}
// ErrorData returns the hex encoded revert reason.
func (e *revertError) ErrorData() interface{} {
return e.reason
}
// Call executes the given transaction on the state for the given block number.
// It doesn't make and changes in the state/blockchain and is useful to execute and retrieve values.
func (s *PublicBlockChainAPI) Call(ctx context.Context, args CallArgs, blockNr rpc.BlockNumber) (hexutil.Bytes, error) {
result, _, _, err := s.doCall(ctx, args, blockNr, vm.Config{}, 5*time.Second)
return (hexutil.Bytes)(result), err
result, _, failed, err, vmErr := s.doCall(ctx, args, blockNr, vm.Config{}, 5*time.Second)
if err != nil {
return nil, err
}
// If the result contains a revert reason, try to unpack and return it.
if failed && len(result) > 0 {
return nil, newRevertError(result)
}
return (hexutil.Bytes)(result), vmErr
}
// EstimateGas returns an estimate of the amount of gas needed to execute the
@ -1145,29 +1190,58 @@ func (s *PublicBlockChainAPI) EstimateGas(ctx context.Context, args CallArgs) (h
cap = hi
// Create a helper to check if a gas allowance results in an executable transaction
executable := func(gas uint64) bool {
executable := func(gas uint64) (bool, []byte, error, error) {
args.Gas = hexutil.Uint64(gas)
_, _, failed, err := s.doCall(ctx, args, rpc.LatestBlockNumber, vm.Config{}, 0)
if err != nil || failed {
log.Warn("[EstimateGas] api", "err", err)
return false
res, _, failed, err, vmErr := s.doCall(ctx, args, rpc.LatestBlockNumber, vm.Config{}, 0)
if err != nil {
if errors.Is(err, core.ErrIntrinsicGas) {
return false, nil, nil, nil // Special case, raise gas limit
}
return false, nil, err, nil // Bail out
}
return true
if failed {
return false, res, nil, vmErr
}
return true, nil, nil, nil
}
// Execute the binary search and hone in on an executable gas limit
for lo+1 < hi {
mid := (hi + lo) / 2
if !executable(mid) {
ok, _, err, _ := executable(mid)
// If the error is not nil(consensus error), it means the provided message
// call or transaction will never be accepted no matter how much gas it is
// assigned. Return the error directly, don't struggle any more.
if err != nil {
return 0, err
}
if !ok {
lo = mid
} else {
hi = mid
}
}
// Reject the transaction as invalid if it still fails at the highest allowance
if hi == cap {
if !executable(hi) {
return 0, fmt.Errorf("gas required exceeds allowance or always failing transaction")
ok, res, err, vmErr := executable(hi)
if err != nil {
return 0, err
}
if !ok {
if vmErr != vm.ErrOutOfGas {
if len(res) > 0 {
return 0, newRevertError(res)
}
return 0, vmErr
}
// Otherwise, the specified gas cap is too low
return 0, fmt.Errorf("gas required exceeds allowance (%d)", cap)
}
}
return hexutil.Uint64(hi), nil

View file

@ -141,7 +141,7 @@ func odrContractCall(ctx context.Context, db ethdb.Database, config *params.Chai
//vmenv := core.NewEnv(statedb, config, bc, msg, header, vm.Config{})
gp := new(core.GasPool).AddGas(math.MaxUint64)
owner := common.Address{}
ret, _, _, _ := core.ApplyMessage(vmenv, msg, gp, owner)
ret, _, _, _, _ := core.ApplyMessage(vmenv, msg, gp, owner)
res = append(res, ret...)
}
} else {
@ -158,7 +158,7 @@ func odrContractCall(ctx context.Context, db ethdb.Database, config *params.Chai
vmenv := vm.NewEVM(context, statedb, nil, config, vm.Config{})
gp := new(core.GasPool).AddGas(math.MaxUint64)
owner := common.Address{}
ret, _, _, _ := core.ApplyMessage(vmenv, msg, gp, owner)
ret, _, _, _, _ := core.ApplyMessage(vmenv, msg, gp, owner)
if statedb.Error() == nil {
res = append(res, ret...)
}

View file

@ -188,7 +188,7 @@ func odrContractCall(ctx context.Context, db ethdb.Database, bc *core.BlockChain
vmenv := vm.NewEVM(context, st, nil, config, vm.Config{})
gp := new(core.GasPool).AddGas(math.MaxUint64)
owner := common.Address{}
ret, _, _, _ := core.ApplyMessage(vmenv, msg, gp, owner)
ret, _, _, _, _ := core.ApplyMessage(vmenv, msg, gp, owner)
res = append(res, ret...)
if st.Error() != nil {
return res, st.Error()

View file

@ -20,7 +20,6 @@ import (
"encoding/hex"
"encoding/json"
"fmt"
"github.com/XinFinOrg/XDPoSChain/core/rawdb"
"math/big"
"strings"
@ -28,6 +27,7 @@ import (
"github.com/XinFinOrg/XDPoSChain/common/hexutil"
"github.com/XinFinOrg/XDPoSChain/common/math"
"github.com/XinFinOrg/XDPoSChain/core"
"github.com/XinFinOrg/XDPoSChain/core/rawdb"
"github.com/XinFinOrg/XDPoSChain/core/state"
"github.com/XinFinOrg/XDPoSChain/core/types"
"github.com/XinFinOrg/XDPoSChain/core/vm"
@ -144,7 +144,7 @@ func (t *StateTest) Run(subtest StateSubtest, vmconfig vm.Config) (*state.StateD
snapshot := statedb.Snapshot()
coinbase := &t.json.Env.Coinbase
if _, _, _, err := core.ApplyMessage(evm, msg, gaspool, *coinbase); err != nil {
if _, _, _, err, _ := core.ApplyMessage(evm, msg, gaspool, *coinbase); err != nil {
statedb.RevertToSnapshot(snapshot)
}
if logs := rlpHash(statedb.Logs()); logs != common.Hash(post.Logs) {