Skip to content

Commit

Permalink
Merge pull request #1217 from libangzhu/plugin-updateChain33
Browse files Browse the repository at this point in the history
feature-ethtx
  • Loading branch information
vipwzw committed Jul 4, 2022
2 parents 2af34a2 + 6ffed26 commit 48c72dc
Show file tree
Hide file tree
Showing 19 changed files with 351 additions and 55 deletions.
3 changes: 3 additions & 0 deletions chain33.fork.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ ForkRootHash=4500000
#地址key格式化, 主要针对eth地址
ForkFormatAddressKey=0

[fork.sub.none]
ForkUseTimeDelay=0

[fork.sub.coins]
Enable=0

Expand Down
3 changes: 3 additions & 0 deletions chain33.para.toml
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,9 @@ ForkRootHash=7200000
#地址key格式化, 主要针对eth地址
ForkFormatAddressKey=0

[fork.sub.none]
ForkUseTimeDelay=0

[fork.sub.coins]
Enable=0

Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ module github.com/33cn/plugin
go 1.16

require (
github.com/33cn/chain33 v1.67.4-0.20220620045433-c377e8e168a8
github.com/33cn/chain33 v1.67.4-0.20220704034506-4c1d3b9170fb
github.com/BurntSushi/toml v0.3.1
github.com/NebulousLabs/Sia v1.3.7
github.com/NebulousLabs/errors v0.0.0-20181203160057-9f787ce8f69e // indirect
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,8 @@ dmitri.shuralyov.com/html/belt v0.0.0-20180602232347-f7d459c86be0/go.mod h1:JLBr
dmitri.shuralyov.com/service/change v0.0.0-20181023043359-a85b471d5412/go.mod h1:a1inKt/atXimZ4Mv927x+r7UpyzRUf4emIoiiSC2TN4=
dmitri.shuralyov.com/state v0.0.0-20180228185332-28bcc343414c/go.mod h1:0PRwlb0D6DFvNNtx+9ybjezNCa8XF0xaYcETyp6rHWU=
git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg=
github.com/33cn/chain33 v1.67.4-0.20220620045433-c377e8e168a8 h1:zI7a1c5VprNKz9WdNGd1cLNRoiLcpe6tdpPDywlzqq8=
github.com/33cn/chain33 v1.67.4-0.20220620045433-c377e8e168a8/go.mod h1:rOabIpP0KWiehXmX6ShOrAveTUvdoQvjUkUePdwk/oQ=
github.com/33cn/chain33 v1.67.4-0.20220704034506-4c1d3b9170fb h1:/INlqCOuY26ntN3UpYKU+nIG6KbQdxGsmqv9S+m1SRY=
github.com/33cn/chain33 v1.67.4-0.20220704034506-4c1d3b9170fb/go.mod h1:uKMKtco0RFJYqJ45wlsTGt0kxQnj2CdFNZTCXLVEIaQ=
github.com/AndreasBriese/bbloom v0.0.0-20180913140656-343706a395b7/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8=
github.com/AndreasBriese/bbloom v0.0.0-20190306092124-e2d15f34fcf9/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8=
github.com/AndreasBriese/bbloom v0.0.0-20190825152654-46b345b51c96 h1:cTp8I5+VIoKjsnZuH8vjyaysT/ses3EvZeaV/1UkF2M=
Expand Down
56 changes: 56 additions & 0 deletions plugin/dapp/evm/executor/evm.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@ import (
"fmt"
"math/big"
"os"
"sort"

log "github.com/33cn/chain33/common/log/log15"
"reflect"

"github.com/33cn/chain33/common/address"
Expand Down Expand Up @@ -149,6 +151,7 @@ func (evm *EVMExecutor) Allow(tx *types.Transaction, index int) error {
if evm.AllowIsUserDot2(exec) {
return nil
}

return types.ErrNotAllow
}

Expand All @@ -167,6 +170,7 @@ func (evm *EVMExecutor) IsFriend(myexec, writekey []byte, othertx *types.Transac
return true
}
}

return false
}

Expand All @@ -186,8 +190,60 @@ func (evm *EVMExecutor) createContractAddress(b common.Address, txHash []byte) c
return common.NewContractAddress(b, txHash)
}

// createContractAddress creates an ethereum address given the bytes and the nonce
func (evm *EVMExecutor) createEvmContractAddress(b common.Address, nonce uint64) common.Address {
return common.NewEvmContractAddress(b, nonce)
}

// CheckTx 校验交易
func (evm *EVMExecutor) CheckTx(tx *types.Transaction, index int) error {
if evm.GetAPI().GetConfig().IsPara() {
return nil
}

if tx == nil {
return fmt.Errorf("tx empty")
}
//main chain
if types.IsEthSignID(tx.GetSignature().GetTy()) {
//获取mempool 某个地址下所有交易
details, err := evm.GetAPI().GetTxListByAddr(&types.ReqAddrs{Addrs: []string{tx.From()}})
if err != nil {
return err
}

txs := details.GetTxs()
txs = append(txs, &types.TransactionDetail{Tx: tx, Index: int64(index)})
if len(txs) > 1 {
sort.SliceStable(txs, func(i, j int) bool { //nonce asc
return txs[i].Tx.GetNonce() < txs[j].Tx.GetNonce()
})
//遇到相同的Nonce ,较低的手续费的交易将被删除
for i, stx := range txs {
if bytes.Equal(stx.Tx.Hash(), tx.Hash()) {
continue
}
if txs[i].GetTx().GetNonce() == tx.GetNonce() {
bnfee := big.NewInt(txs[i].GetTx().Fee)
bnfee = bnfee.Mul(bnfee, big.NewInt(110))
bnfee = bnfee.Div(bnfee, big.NewInt(1e2))
if tx.Fee < bnfee.Int64() {
err := fmt.Errorf("requires at least 10 percent increase in handling fee,need more:%d", bnfee.Int64()-tx.Fee)
log.Error("checkTxNonce", "fee err", err, "txfee", tx.Fee, "mempooltx", txs[0].GetTx().Fee)
return err
}
//移除手续费较低的交易
evm.GetAPI().RemoveTxsByHashList(&types.TxHashList{
Hashes: [][]byte{txs[i].GetTx().Hash()},
})
return nil
}
}

}

}

return nil
}

Expand Down
27 changes: 17 additions & 10 deletions plugin/dapp/evm/executor/exec.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ package executor

import (
"encoding/hex"
"errors"
"fmt"
"strings"
"sync/atomic"
Expand Down Expand Up @@ -38,19 +37,22 @@ func (evm *EVMExecutor) Exec(tx *types.Transaction, index int) (*types.Receipt,
evmDebugInited = true
}

return evm.innerExec(msg, tx.Hash(), index, msg.GasLimit(), false)
receipt, err := evm.innerExec(msg, tx.Hash(), tx.GetSignature().GetTy(), index, msg.GasLimit(), false)
return receipt, err
}

// 通用的EVM合约执行逻辑封装
// readOnly 是否只读调用,仅执行evm abi查询时为true
func (evm *EVMExecutor) innerExec(msg *common.Message, txHash []byte, index int, txFee uint64, readOnly bool) (receipt *types.Receipt, err error) {
func (evm *EVMExecutor) innerExec(msg *common.Message, txHash []byte, sigType int32, index int, txFee uint64, readOnly bool) (receipt *types.Receipt, err error) {
// 获取当前区块的上下文信息构造EVM上下文
context := evm.NewEVMContext(msg, txHash)
cfg := evm.GetAPI().GetConfig()
// 创建EVM运行时对象
env := runtime.NewEVM(context, evm.mStateDB, *evm.vmCfg, cfg)
isCreate := strings.Compare(msg.To().String(), EvmAddress) == 0 && len(msg.Data()) > 0
isTransferOnly := strings.Compare(msg.To().String(), EvmAddress) == 0 && 0 == len(msg.Data())
log.Info("innerExec", "isCreate", isCreate, "isTransferOnly", isTransferOnly, "evmaddr", EvmAddress, "msg.From:", msg.From(), "msg.To", msg.To().String(),
"data size:", len(msg.Data()), "readOnly", readOnly)
var (
ret []byte
vmerr error
Expand All @@ -64,20 +66,25 @@ func (evm *EVMExecutor) innerExec(msg *common.Message, txHash []byte, index int,
if isTransferOnly {
caller := msg.From()
receiver := common.BytesToAddress(msg.Para())

if !evm.mStateDB.CanTransfer(caller.String(), msg.Value()) {
log.Error("innerExec", "Not enough balance to be transferred from", caller.String(), "amout", msg.Value())
return nil, types.ErrNoBalance
}

env.StateDB.Snapshot()
env.Transfer(env.StateDB, caller, receiver, msg.Value())
curVer := evm.mStateDB.GetLastSnapshot()
kvSet, logs := evm.mStateDB.GetChangedData(curVer.GetID())
receipt = &types.Receipt{Ty: types.ExecOk, KV: kvSet, Logs: logs}
return receipt, nil
} else if isCreate {
// 使用随机生成的地址作为合约地址(这个可以保证每次创建的合约地址不会重复,不存在冲突的情况)
contractAddr = evm.createContractAddress(msg.From(), txHash)
if types.IsEthSignID(int32(sigType)) {
// 通过ethsign 签名的兼容交易 采用from+nonce 创建合约地址
contractAddr = evm.createEvmContractAddress(msg.From(), uint64(msg.Nonce()))
} else {
contractAddr = evm.createContractAddress(msg.From(), txHash)
}

contractAddrStr = contractAddr.String()
if !env.StateDB.Empty(contractAddrStr) {
return receipt, model.ErrContractAddressCollision
Expand All @@ -98,6 +105,7 @@ func (evm *EVMExecutor) innerExec(msg *common.Message, txHash []byte, index int,
evm.mStateDB.Prepare(common.BytesToHash(txHash), index)

if isCreate {

ret, snapshot, leftOverGas, vmerr = env.Create(runtime.AccountRef(msg.From()), contractAddr, msg.Data(), context.GasLimit, execName, msg.Alias(), msg.Value())
} else {
callPara := msg.Para()
Expand All @@ -124,7 +132,7 @@ func (evm *EVMExecutor) innerExec(msg *common.Message, txHash []byte, index int,
visiableOut = append(visiableOut, ret[i])
}
ret = visiableOut
vmerr = errors.New(fmt.Sprintf("%s,detail: %s", vmerr.Error(), string(ret)))
vmerr = fmt.Errorf("%s,detail: %s", vmerr.Error(), string(ret))
log.Error("evm contract exec error", "error info", vmerr, "ret", string(ret))

return receipt, vmerr
Expand Down Expand Up @@ -180,11 +188,10 @@ func (evm *EVMExecutor) innerExec(msg *common.Message, txHash []byte, index int,

evm.collectEvmTxLog(txHash, contractReceipt, receipt)

if isCreate {
if isCreate && !readOnly {
log.Info("innerExec", "Succeed to created new contract with name", msg.Alias(),
"created contract address", contractAddrStr)
}

return receipt, nil
}

Expand Down Expand Up @@ -244,7 +251,7 @@ func (evm *EVMExecutor) GetMessage(tx *types.Transaction, index int, fromPtr *co
if gasPrice == 0 {
gasPrice = uint32(1)
}

log.Debug("GetMessage", "code size", len(action.Code), "data size:", len(action.Para))
// 合约的GasLimit即为调用者为本次合约调用准备支付的手续费
msg = common.NewMessage(from, to, tx.Nonce, action.Amount, gasLimit, gasPrice, action.Code, action.Para, action.GetAlias())
return msg, err
Expand Down
24 changes: 24 additions & 0 deletions plugin/dapp/evm/executor/exec_del_local.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
package executor

import (
"github.com/33cn/chain33/system/crypto/secp256k1eth"
"github.com/33cn/chain33/types"
evmtypes "github.com/33cn/plugin/plugin/dapp/evm/types"
)
Expand All @@ -15,6 +16,29 @@ func (evm *EVMExecutor) ExecDelLocal(tx *types.Transaction, receipt *types.Recei
if err != nil {
return nil, err
}

defer func(lSet *types.LocalDBSet) {
if types.IsEthSignID(tx.GetSignature().GetTy()) {
nonceLocalKey := secp256k1eth.CaculCoinsEvmAccountKey(tx.From())
nonceV, err := evm.GetLocalDB().Get(nonceLocalKey)
if err == nil {
var evmNonce types.EvmAccountNonce
types.Decode(nonceV, &evmNonce)
if evmNonce.GetNonce() == tx.GetNonce()+1 {
evmNonce.Nonce--
if evmNonce.GetNonce() < 0 {
evmNonce.Nonce = 0
}
if lSet != nil {
lSet.KV = append(lSet.KV, &types.KeyValue{Key: nonceLocalKey, Value: types.Encode(&evmNonce)})
}
}

}

}
}(set)

if receipt.GetTy() != types.ExecOk {
return set, nil
}
Expand Down
24 changes: 24 additions & 0 deletions plugin/dapp/evm/executor/exec_local.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ package executor
import (
"bytes"

"github.com/33cn/chain33/system/crypto/secp256k1eth"
"github.com/33cn/chain33/types"
evmtypes "github.com/33cn/plugin/plugin/dapp/evm/types"
)
Expand All @@ -17,6 +18,28 @@ func (evm *EVMExecutor) ExecLocal(tx *types.Transaction, receipt *types.ReceiptD
if err != nil {
return nil, err
}

defer func(lSet *types.LocalDBSet) {
if types.IsEthSignID(tx.GetSignature().GetTy()) {
nonceLocalKey := secp256k1eth.CaculCoinsEvmAccountKey(tx.From())
nonceV, err := evm.GetLocalDB().Get(nonceLocalKey)
var evmNonce types.EvmAccountNonce
if err == nil {
types.Decode(nonceV, &evmNonce)
if evmNonce.GetNonce() == tx.GetNonce() {
evmNonce.Nonce++
}

} else {
evmNonce.Addr = tx.From()
evmNonce.Nonce = 1
}
if lSet != nil {
lSet.KV = append(lSet.KV, &types.KeyValue{Key: nonceLocalKey, Value: types.Encode(&evmNonce)})
}
}
}(set)

if receipt.GetTy() != types.ExecOk {
return set, nil
}
Expand All @@ -43,6 +66,7 @@ func (evm *EVMExecutor) ExecLocal(tx *types.Transaction, receipt *types.ReceiptD
}
}
}

set.KV = evm.AddRollbackKV(tx, []byte(evmtypes.ExecutorName), set.KV)
return set, err
}
37 changes: 32 additions & 5 deletions plugin/dapp/evm/executor/query.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import (
"strings"
"sync/atomic"

log "github.com/33cn/chain33/common/log/log15"

"github.com/33cn/plugin/plugin/dapp/evm/executor/vm/runtime"

"github.com/33cn/chain33/common"
Expand Down Expand Up @@ -79,15 +81,14 @@ func (evm *EVMExecutor) Query_EstimateGas(req *evmtypes.EstimateEVMGasReq) (type
}

msg.SetGasLimit(evmtypes.MaxGasLimit)
receipt, err := evm.innerExec(msg, tx.Hash(), index, evmtypes.MaxGasLimit, true)
receipt, err := evm.innerExec(msg, tx.Hash(), tx.GetSignature().GetTy(), index, evmtypes.MaxGasLimit, true)
if err != nil {
return nil, err
}

if receipt.Ty != types.ExecOk {
return nil, errors.New("contract call error")
}

callData := getCallReceipt(receipt.GetLogs())
if callData == nil {
return nil, errors.New("nil receipt")
Expand Down Expand Up @@ -163,7 +164,7 @@ func (evm *EVMExecutor) Query_Query(in *evmtypes.EvmQueryReq) (types.Message, er
msg := evmCommon.NewMessage(caller, evmCommon.StringToAddress(in.Address), 0, 0, evmtypes.MaxGasLimit, 1, nil, evmCommon.FromHex(in.Input), "estimateGas")
txHash := evmCommon.BigToHash(big.NewInt(evmtypes.MaxGasLimit)).Bytes()

receipt, err := evm.innerExec(msg, txHash, 1, evmtypes.MaxGasLimit, true)
receipt, err := evm.innerExec(msg, txHash, 0, 1, evmtypes.MaxGasLimit, true)
if err != nil {
ret.JsonData = fmt.Sprintf("%v", err)
return ret, nil
Expand All @@ -179,13 +180,14 @@ func (evm *EVMExecutor) Query_Query(in *evmtypes.EvmQueryReq) (types.Message, er
return ret, nil
}

//Query_GetNonce 获取普通账户的Nonce
func (evm *EVMExecutor) Query_GetNonce(in *evmtypes.EvmGetNonceReq) (types.Message, error) {
evm.CheckInit()
nonce := evm.mStateDB.GetNonce(in.Address)

nonce := evm.mStateDB.GetAccountNonce(in.Address)
return &evmtypes.EvmGetNonceRespose{Nonce: int64(nonce)}, nil
}

//Query_GetPackData ...
func (evm *EVMExecutor) Query_GetPackData(in *evmtypes.EvmGetPackDataReq) (types.Message, error) {
evm.CheckInit()
_, packData, err := evmAbi.Pack(in.Parameter, in.Abi, false)
Expand All @@ -197,6 +199,7 @@ func (evm *EVMExecutor) Query_GetPackData(in *evmtypes.EvmGetPackDataReq) (types
return &evmtypes.EvmGetPackDataRespose{PackData: packStr}, nil
}

//Query_GetUnpackData ...
func (evm *EVMExecutor) Query_GetUnpackData(in *evmtypes.EvmGetUnpackDataReq) (types.Message, error) {
evm.CheckInit()
data, err := common.FromHex(in.Data)
Expand All @@ -216,3 +219,27 @@ func (evm *EVMExecutor) Query_GetUnpackData(in *evmtypes.EvmGetUnpackDataReq) (t
}
return &ret, nil
}

//Query_GetCode 获取合约地址下的code
func (evm *EVMExecutor) Query_GetCode(in *evmtypes.CheckEVMAddrReq) (types.Message, error) {
evm.CheckInit()
addrStr := in.Addr
if len(addrStr) == 0 {
return nil, model.ErrAddrNotExists
}

addr := evmCommon.StringToAddress(in.GetAddr())
log.Debug("Query_GetCode", "addr", in.GetAddr(), "addrstring", addr.String())
codeData := evm.mStateDB.GetCode(addr.String())
abiData := evm.mStateDB.GetAbi(addr.String())
account := evm.mStateDB.GetAccount(addr.String())
var ret evmtypes.EVMContractData
ret.Code = codeData
ret.Abi = abiData
if account != nil {
ret.Creator = account.GetCreator()
ret.Alias = account.GetAliasName()
}
return &ret, nil

}
Loading

0 comments on commit 48c72dc

Please sign in to comment.