diff --git a/cmd/chain33/chain33.fork.toml b/cmd/chain33/chain33.fork.toml index eff5c318a0..921312d6d3 100644 --- a/cmd/chain33/chain33.fork.toml +++ b/cmd/chain33/chain33.fork.toml @@ -25,6 +25,7 @@ ForkTicketFundAddrV1=3350000 ForkRootHash=4500000 ForkFormatAddressKey=0 ForkCheckEthTxSort=0 +ForkProxyExec=0 [fork.sub.none] ForkUseTimeDelay=0 diff --git a/cmd/chain33/chain33.system.fork.toml b/cmd/chain33/chain33.system.fork.toml index b9210f2c69..74f579ecda 100644 --- a/cmd/chain33/chain33.system.fork.toml +++ b/cmd/chain33/chain33.system.fork.toml @@ -25,3 +25,4 @@ ForkTicketFundAddrV1=3350000 ForkRootHash=4500000 ForkFormatAddressKey=0 ForkCheckEthTxSort=0 +ForkProxyExec=0 diff --git a/cmd/chain33/chain33.test.toml b/cmd/chain33/chain33.test.toml index 4741a3922e..1ee425815a 100644 --- a/cmd/chain33/chain33.test.toml +++ b/cmd/chain33/chain33.test.toml @@ -207,8 +207,14 @@ coinType="bty" minerwhitelist=["*"] [exec] +#交易费相关统一在mempool中配置 +#是否开启stat插件 enableStat=false +#是否开启MVCC插件 enableMVCC=false +alias=["token1:token","token2:token","token3:token"] +#代理执行器地址 +proxyExecAddress="0x0000000000000000000000000000000000200005" [exec.sub.token] saveTokenTxList=true diff --git a/cmd/chain33/chain33.toml b/cmd/chain33/chain33.toml index c0cf1c4087..c0f7e99b46 100644 --- a/cmd/chain33/chain33.toml +++ b/cmd/chain33/chain33.toml @@ -306,7 +306,8 @@ enableStat=false #是否开启MVCC插件 enableMVCC=false alias=["token1:token","token2:token","token3:token"] - +#代理执行器地址 +proxyExecAddrss="0x0000000000000000000000000000000000200005" [exec.sub.token] #是否保存token交易信息 saveTokenTxList=true diff --git a/executor/execenv.go b/executor/execenv.go index bcf0ad7467..704e3bcf40 100644 --- a/executor/execenv.go +++ b/executor/execenv.go @@ -6,7 +6,8 @@ package executor import ( "bytes" - + "errors" + "fmt" "github.com/33cn/chain33/account" "github.com/33cn/chain33/client" "github.com/33cn/chain33/client/api" @@ -598,6 +599,42 @@ func (e *executor) rollback() { } } +func (e *executor) proxyGetRealTx(tx *types.Transaction) (*types.Transaction, error) { + if string(types.GetRealExecName(tx.GetExecer())) != "evm" { + return nil, fmt.Errorf("execName %s not allowd", string(types.GetRealExecName(tx.GetExecer()))) + } + var actionData types.EVMContractAction4Chain33 + err := types.Decode(tx.GetPayload(), &actionData) + if err != nil { + return nil, err + } + if len(actionData.GetPara()) == 0 { + return nil, errors.New("empty tx") + } + var realTx types.Transaction + err = types.Decode(actionData.Para, &realTx) + if err != nil { + return nil, err + } + + return &realTx, nil + +} + +func (e *executor) proxyExecTx(tx *types.Transaction) (*types.Transaction, error) { + var realTx = tx + var err error + if tx.To == e.cfg.GetModuleConfig().Exec.ProxyExecAddress { + realTx, err = e.proxyGetRealTx(tx) + if err != nil { + return realTx, err + } + realTx.Signature = tx.Signature + + } + return realTx, nil +} + func (e *executor) execTx(exec *Executor, tx *types.Transaction, index int) (*types.Receipt, error) { if e.height == 0 { //genesis block 不检查手续费 receipt, err := e.Exec(tx, index) @@ -609,10 +646,20 @@ func (e *executor) execTx(exec *Executor, tx *types.Transaction, index int) (*ty } return receipt, nil } + + var err error + //代理执行 EVM-->txpayload-->chain33 tx + if e.cfg.IsFork(e.height, "ForkProxyExec") { + tx, err = e.proxyExecTx(tx) + if err != nil { + return nil, err + } + } + //交易检查规则: //1. mempool 检查区块,尽量检查更多的错误 //2. 打包的时候,尽量打包更多的交易,只要基本的签名,以及格式没有问题 - err := e.checkTx(tx, index) + err = e.checkTx(tx, index) if err != nil { elog.Error("execTx.checkTx ", "txhash", common.ToHex(tx.Hash()), "err", err) if e.cfg.IsPara() { diff --git a/executor/execenv_test.go b/executor/execenv_test.go index fb6cace584..f8c9ce35ce 100644 --- a/executor/execenv_test.go +++ b/executor/execenv_test.go @@ -5,11 +5,16 @@ package executor import ( + "github.com/33cn/chain33/common/crypto" + erpctypes "github.com/33cn/chain33/rpc/ethrpc/types" + drivers "github.com/33cn/chain33/system/dapp" + ecommon "github.com/ethereum/go-ethereum/common" + ethtypes "github.com/ethereum/go-ethereum/core/types" + ethcrypto "github.com/ethereum/go-ethereum/crypto" + "math/big" "testing" "time" - drivers "github.com/33cn/chain33/system/dapp" - "strings" _ "github.com/33cn/chain33/system" @@ -19,6 +24,7 @@ import ( ) func TestLoadDriverFork(t *testing.T) { + str := types.GetDefaultCfgstring() new := strings.Replace(str, "Title=\"local\"", "Title=\"chain33\"", 1) exec, _ := initEnv(types.MergeCfg(types.ReadFile("../cmd/chain33/chain33.fork.toml"), new)) @@ -97,3 +103,61 @@ func (app *notAllowApp) Allow(tx *types.Transaction, index int) error { } return types.ErrActionNotSupport } + +func TestProxyExec(t *testing.T) { + exec, _ := initEnv(types.GetDefaultCfgstring()) + cfg := exec.client.GetConfig() + ctx := &executorCtx{ + stateHash: nil, + height: 0, + blocktime: time.Now().Unix(), + difficulty: 1, + mainHash: nil, + parentHash: nil, + } + + execute := newExecutor(ctx, exec, nil, nil, nil) + //测试解析代理地址 + proxyAddr := ecommon.HexToAddress("0x0000000000000000000000000000000000200005") + var hexKey = "7939624566468cfa3cb2c9f39d5ad83bdc7cf4356bfd1a7b8094abda6b0699d1" + sk, err := ethcrypto.ToECDSA(ecommon.FromHex(hexKey)) + assert.Nil(t, err) + + signer := ethtypes.NewEIP155Signer(big.NewInt(3999)) + //构建eth交易 + to, _ := util.Genaddress() + //coins 转账,没有签名的裸交易 + coinsTx := util.CreateCoinsTx(cfg, nil, to, 1000) + etx := ethtypes.NewTransaction(uint64(0), proxyAddr, big.NewInt(0), 3000000, big.NewInt(10e9), types.Encode(coinsTx)) + signtx, err := ethtypes.SignTx(etx, signer, sk) + assert.Nil(t, err) + v, r, s := signtx.RawSignatureValues() + cv, err := erpctypes.CaculateRealV(v, signtx.ChainId().Uint64(), signtx.Type()) + assert.Nil(t, err) + sig := make([]byte, 65) + copy(sig[32-len(r.Bytes()):32], r.Bytes()) + copy(sig[64-len(s.Bytes()):64], s.Bytes()) + sig[64] = cv + txSha3 := signer.Hash(signtx) + pubkey, err := ethcrypto.Ecrecover(txSha3.Bytes(), sig) + assert.Nil(t, err) + assembleTx := erpctypes.AssembleChain33Tx(signtx, sig, pubkey, cfg) + //checkSign + err = execute.checkTx(assembleTx, 0) + assert.Errorf(t, err, "ErrExecNameNotAllow") + types.AllowUserExec = append(types.AllowUserExec, []byte("evm")) + err = execute.checkTx(assembleTx, 0) + assert.Nil(t, err) + + crypto.Init(cfg.GetModuleConfig().Crypto, cfg.GetSubConfig().Crypto) + assert.True(t, assembleTx.CheckSign(0)) + //解析交易 + realTx, err := execute.proxyExecTx(assembleTx) + assert.Nil(t, err) + assert.Equal(t, "0xa42431da868c58877a627cc71dc95f01bf40c196", realTx.From()) + testTx := realTx.Clone() + testTx.Signature = nil + + //与原始交易对比 + assert.Equal(t, coinsTx.Hash(), testTx.Hash()) +} diff --git a/executor/executor_real_test.go b/executor/executor_real_test.go index 587df9f851..989f0947b3 100644 --- a/executor/executor_real_test.go +++ b/executor/executor_real_test.go @@ -7,12 +7,6 @@ package executor_test import ( "errors" "fmt" - "net/http" - _ "net/http/pprof" - "testing" - - "sync" - "github.com/33cn/chain33/common" "github.com/33cn/chain33/common/address" "github.com/33cn/chain33/common/merkle" @@ -22,6 +16,10 @@ import ( "github.com/33cn/chain33/util" "github.com/33cn/chain33/util/testnode" "github.com/stretchr/testify/assert" + "net/http" + _ "net/http/pprof" + "sync" + "testing" ) var runonce sync.Once diff --git a/queue/queue_test.go b/queue/queue_test.go index f07437e129..4d96bf9052 100644 --- a/queue/queue_test.go +++ b/queue/queue_test.go @@ -512,6 +512,7 @@ func TestChannelClose(t *testing.T) { go q.Start() //rpc 模块 会向其他模块发送消息,自己本身不需要订阅消息 go func() { + time.Sleep(time.Millisecond * 100) done <- struct{}{} }() for i := 0; i < 10000; i++ { diff --git a/rpc/ethrpc/eth/eth.go b/rpc/ethrpc/eth/eth.go index fbdd5ceaa8..0efa9d5b07 100644 --- a/rpc/ethrpc/eth/eth.go +++ b/rpc/ethrpc/eth/eth.go @@ -560,6 +560,17 @@ func (e *ethHandler) EstimateGas(callMsg *types.CallMsg) (hexutil.Uint64, error) }) fee := properFee.GetProperFee() + //GetMinTxFeeRate 默认1e5 + realFee, _ := tx.GetRealFee(e.cfg.GetMinTxFeeRate()) + //判断是否是代理执行的地址,如果是,则直接返回,不会交给evm执行器去模拟执行计算gas. + if callMsg.To == e.cfg.GetModuleConfig().Exec.ProxyExecAddress { + rightFee := realFee + if realFee < fee { + rightFee = fee + } + return hexutil.Uint64(rightFee), nil + } + var minimumGas int64 = 21000 if callMsg.Data == nil || len(*callMsg.Data) == 0 { if fee < e.cfg.GetMinTxFeeRate() { @@ -597,8 +608,6 @@ func (e *ethHandler) EstimateGas(callMsg *types.CallMsg) (hexutil.Uint64, error) } bigGas, _ := new(big.Int).SetString(gas.Gas, 10) - //GetMinTxFeeRate 默认1e5 - realFee, _ := tx.GetRealFee(e.cfg.GetMinTxFeeRate()) var finalFee = realFee if bigGas.Uint64() > uint64(realFee) { diff --git a/system/mempool/check.go b/system/mempool/check.go index 9f2d861ce5..a64dced207 100644 --- a/system/mempool/check.go +++ b/system/mempool/check.go @@ -1,7 +1,11 @@ package mempool import ( + "bytes" "errors" + "fmt" + "math/big" + "sort" "sync/atomic" "time" @@ -198,6 +202,13 @@ func (mem *Mempool) checkTxRemote(msg *queue.Message) *queue.Message { } } + //检查mempool内是否有相同的tx.nonce + err = mem.evmTxNonceCheck(tx.Tx()) + if err != nil { + msg.Data = err + return msg + } + err = mem.PushTx(tx.Tx()) if err != nil { if err == types.ErrMemFull { @@ -209,3 +220,52 @@ func (mem *Mempool) checkTxRemote(msg *queue.Message) *queue.Message { } return msg } + +//evmTxNonceCheck 检查eth noce 是否有重复值,如果有的话,需要比较txFee大小,用于替换较小的fee的那笔交易 +func (mem *Mempool) evmTxNonceCheck(tx *types.Transaction) error { + if !types.IsEthSignID(tx.Tx().GetSignature().GetTy()) { + return nil + } + + //较小的nonce 则返回错误,不被允许进入mempool + if tx.GetNonce() < mem.getCurrentNonce(tx.From()) { + return types.ErrLowNonce + } + details := mem.GetAccTxs(&types.ReqAddrs{Addrs: []string{tx.From()}}) + txs := details.GetTxs() + txs = append(txs, &types.TransactionDetail{Tx: tx, Index: int64(len(txs))}) + 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) + //相同的nonce,fee 必须提升至1.1 倍 才能有效替换之前的交易 + 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) + mlog.Error("checkTxNonce", "fee err", err, "txfee", tx.Fee, "mempooltx", txs[0].GetTx().Fee, "from:", tx.From()) + return err + } + + //删除Expire 较大的交易或者更低手续费的交易,确保先创建的交易留在mempool 中 + mem.RemoveTxs(&types.TxHashList{ + Hashes: [][]byte{txs[i].GetTx().Hash()}, + }) + mlog.Info("evmTxNonceCheck", "remote txhash:", common.ToHex(txs[i].GetTx().Hash()), "replace txHash:", common.ToHex(tx.Hash())) + return nil + } + } + + } + + return nil + +} diff --git a/system/mempool/mempool_test.go b/system/mempool/mempool_test.go index 4efd0fb6ca..bd7d8f651d 100644 --- a/system/mempool/mempool_test.go +++ b/system/mempool/mempool_test.go @@ -7,6 +7,9 @@ package mempool import ( "errors" "fmt" + "github.com/33cn/chain33/system/address/eth" + "github.com/33cn/chain33/system/crypto/secp256k1eth" + "github.com/stretchr/testify/assert" "math/rand" "testing" @@ -1475,3 +1478,55 @@ func Test_sortEthSignTyTx(t *testing.T) { require.Equal(t, txs[3].GetNonce(), tx4.GetNonce()) } + +func TestCheckTxsNonce(t *testing.T) { + var err error + c, _ = crypto.Load(types.GetSignName("", types.SECP256K1ETH), -1) + key, _ := common.FromHex(hexPirv) + privKey, err = c.PrivKeyFromBytes(key) + assert.Nil(t, err) + tx0 := &types.Transaction{ChainID: 0, Execer: []byte("evm"), Payload: types.Encode(transfer), Fee: 460000000, Expire: 0, To: toAddr, Nonce: 0} + tx0.Sign(types.EncodeSignID(secp256k1eth.ID, eth.ID), privKey) + tx1 := &types.Transaction{ChainID: 0, Execer: []byte("evm"), Payload: types.Encode(transfer), Fee: 460000000, Expire: 0, To: toAddr, Nonce: 1} + tx1.Sign(types.EncodeSignID(secp256k1eth.ID, eth.ID), privKey) + tx2 := &types.Transaction{ChainID: 0, Execer: []byte("evm"), Payload: types.Encode(transfer), Fee: 460000002, Expire: 0, To: toAddr, Nonce: 1} + tx2.Sign(types.EncodeSignID(secp256k1eth.ID, eth.ID), privKey) + tx3 := &types.Transaction{ChainID: 0, Execer: []byte("evm"), Payload: types.Encode(transfer), Fee: 460000002 + 45999998, Expire: 0, To: toAddr, Nonce: 1} + tx3.Sign(types.EncodeSignID(secp256k1eth.ID, eth.ID), privKey) + _, mem := initEnv(10) + //测试nonce 较低的情况下进入mempool 检查 + msg := mem.client.NewMessage("mempool", types.EventTx, tx0) + mem.client.Send(msg, true) + msg, _ = mem.client.Wait(msg) + reply := msg.GetData().(*types.Reply) + assert.False(t, reply.GetIsOk()) + assert.Equal(t, "ErrNonceTooLow", string(reply.GetMsg())) + + msg = mem.client.NewMessage("mempool", types.EventTx, tx1) + mem.client.Send(msg, true) + msg, _ = mem.client.Wait(msg) + reply = msg.GetData().(*types.Reply) + assert.True(t, reply.GetIsOk()) + //相同的nonce的交易,在gas 不满足条件下,不允许通过过 + msg = mem.client.NewMessage("mempool", types.EventTx, tx2) + mem.client.Send(msg, true) + msg, err = mem.client.Wait(msg) + assert.Nil(t, err) + reply = msg.GetData().(*types.Reply) + assert.False(t, reply.GetIsOk()) + assert.Equal(t, "requires at least 10 percent increase in handling fee,need more:45999998", string(reply.GetMsg())) + txs := mem.GetLatestTx() + assert.Equal(t, 1, len(txs)) + assert.Equal(t, txs[0].Hash(), tx1.Hash()) + msg = mem.client.NewMessage("mempool", types.EventTx, tx3) + mem.client.Send(msg, true) + msg, err = mem.client.Wait(msg) + assert.Nil(t, err) + reply = msg.GetData().(*types.Reply) + assert.True(t, reply.GetIsOk()) + + //此时mempool 中应该之后tx3 ,tx1 已经被自动删除 + txs = mem.GetLatestTx() + assert.Equal(t, 1, len(txs)) + assert.Equal(t, txs[0].Hash(), tx3.Hash()) +} diff --git a/system/p2p/dht/p2p_test.go b/system/p2p/dht/p2p_test.go index 2904679096..e4e879c155 100644 --- a/system/p2p/dht/p2p_test.go +++ b/system/p2p/dht/p2p_test.go @@ -6,7 +6,8 @@ import ( "encoding/hex" "encoding/json" "fmt" - + "github.com/libp2p/go-libp2p" + "github.com/multiformats/go-multiaddr" "github.com/stretchr/testify/mock" clientMocks "github.com/33cn/chain33/client/mocks" @@ -29,13 +30,11 @@ import ( p2pty "github.com/33cn/chain33/system/p2p/dht/types" "github.com/33cn/chain33/types" "github.com/33cn/chain33/util" - "github.com/libp2p/go-libp2p" "github.com/libp2p/go-libp2p/core/crypto" "github.com/libp2p/go-libp2p/core/host" "github.com/libp2p/go-libp2p/core/metrics" "github.com/libp2p/go-libp2p/core/peer" "github.com/libp2p/go-libp2p/core/protocol" - "github.com/multiformats/go-multiaddr" "github.com/stretchr/testify/require" ) diff --git a/types/cfg.go b/types/cfg.go index 6e6d289f9c..c7d0a9f3e0 100644 --- a/types/cfg.go +++ b/types/cfg.go @@ -314,12 +314,13 @@ type Exec struct { DisableAddrIndex bool `json:"disableAddrIndex,omitempty"` Alias []string `json:"alias,omitempty"` // 是否保存token交易信息 - SaveTokenTxList bool `json:"saveTokenTxList,omitempty"` - EnableAddrFeeIndex bool `json:"enableAddrFeeIndex,omitempty"` - DisableTxIndex bool `json:"disableTxIndex,omitempty"` - DisableFeeIndex bool `json:"disableFeeIndex,omitempty"` - DisableTxDupCheck bool `json:"disableTxDupCheck,omitempty"` - DisableExecLocal bool `json:"disableExecLocal,omitempty"` + SaveTokenTxList bool `json:"saveTokenTxList,omitempty"` + EnableAddrFeeIndex bool `json:"enableAddrFeeIndex,omitempty"` + DisableTxIndex bool `json:"disableTxIndex,omitempty"` + DisableFeeIndex bool `json:"disableFeeIndex,omitempty"` + DisableTxDupCheck bool `json:"disableTxDupCheck,omitempty"` + DisableExecLocal bool `json:"disableExecLocal,omitempty"` + ProxyExecAddress string `json:"proxyExecAddress,omitempty"` } // Pprof 配置 diff --git a/types/defaultcfg.go b/types/defaultcfg.go index e922bf4589..5e15cf57ee 100644 --- a/types/defaultcfg.go +++ b/types/defaultcfg.go @@ -23,7 +23,9 @@ enableTypes=[] #设置启用的加密插件名称,不配置启用所有 [crypto.enableHeight] #配置已启用插件的启用高度,不配置采用默认高度0, 负数表示不启用 secp256k1=0 [crypto.sub.secp256k1] #支持插件子配置 -[crypto.sub.secp256k1eth] #支持插件子配置 + +[crypto.sub.secp256k1eth] +#兼容EVM链的链ID evmChainID=3999 [log] # 日志级别,支持debug(dbug)/info/warn/error(eror)/crit @@ -202,8 +204,13 @@ minerwhitelist=["*"] [exec] enableStat=false enableMVCC=false + +#代理执行器地址 +proxyExecAddress="0x0000000000000000000000000000000000200005" alias=["token1:token","token2:token","token3:token"] [exec.sub.coins] +#允许evm执行器操作coins +friendExecer=["evm"] [exec.sub.token] saveTokenTxList=true diff --git a/types/error.go b/types/error.go index 588c3f25bc..382f764c23 100644 --- a/types/error.go +++ b/types/error.go @@ -207,4 +207,5 @@ var ( ErrPushNotSubscribed = errors.New("ErrPushNotSubscribed") ErrTxChainID = errors.New("ErrTxChainID") ErrTimeout = errors.New("ErrTimeout") + ErrLowNonce = errors.New("ErrNonceTooLow") ) diff --git a/types/fork.go b/types/fork.go index eec6983412..a2bdf29f47 100644 --- a/types/fork.go +++ b/types/fork.go @@ -143,6 +143,7 @@ func (f *Forks) SetTestNetFork() { f.SetFork("ForkRootHash", 4500000) f.SetFork(address.ForkFormatAddressKey, 0) f.setFork("ForkCheckEthTxSort", 0) + f.setFork("ForkProxyExec", 0) } func (f *Forks) setLocalFork() { diff --git a/wallet/common/walletoperate.go b/wallet/common/walletoperate.go index b981260b69..a04815d5fb 100644 --- a/wallet/common/walletoperate.go +++ b/wallet/common/walletoperate.go @@ -71,6 +71,6 @@ type WalletOperate interface { WaitTx(hash []byte) *types.TransactionDetail WaitTxs(hashes [][]byte) (ret []*types.TransactionDetail) - SendTransaction(payload types.Message, execer []byte, priv crypto.PrivKey, to string) (hash []byte, err error) - SendToAddress(priv crypto.PrivKey, addrto string, amount int64, note string, Istoken bool, tokenSymbol string) (*types.ReplyHash, error) + SendTransaction(payload types.Message, execer []byte, priv crypto.PrivKey, addressID int32, to string) (hash []byte, err error) + SendToAddress(priv crypto.PrivKey, addressID int32, addrto string, amount int64, note string, Istoken bool, tokenSymbol string) (*types.ReplyHash, error) } diff --git a/wallet/sendtx.go b/wallet/sendtx.go index a050b79cda..5970a803fb 100644 --- a/wallet/sendtx.go +++ b/wallet/sendtx.go @@ -88,8 +88,8 @@ func (wallet *Wallet) GetHeight() int64 { return h } -func (wallet *Wallet) sendTransactionWait(payload types.Message, execer []byte, priv crypto.PrivKey, to string) (err error) { - hash, err := wallet.sendTransaction(payload, execer, priv, to) +func (wallet *Wallet) sendTransactionWait(payload types.Message, execer []byte, priv crypto.PrivKey, addressID int32, to string) (err error) { + hash, err := wallet.sendTransaction(payload, execer, priv, addressID, to) if err != nil { return err } @@ -101,17 +101,17 @@ func (wallet *Wallet) sendTransactionWait(payload types.Message, execer []byte, } // SendTransaction 发送一笔交易 -func (wallet *Wallet) SendTransaction(payload types.Message, execer []byte, priv crypto.PrivKey, to string) (hash []byte, err error) { +func (wallet *Wallet) SendTransaction(payload types.Message, execer []byte, priv crypto.PrivKey, addressID int32, to string) (hash []byte, err error) { if !wallet.isInited() { return nil, types.ErrNotInited } wallet.mtx.Lock() defer wallet.mtx.Unlock() - return wallet.sendTransaction(payload, execer, priv, to) + return wallet.sendTransaction(payload, execer, priv, addressID, to) } -func (wallet *Wallet) sendTransaction(payload types.Message, execer []byte, priv crypto.PrivKey, to string) (hash []byte, err error) { +func (wallet *Wallet) sendTransaction(payload types.Message, execer []byte, priv crypto.PrivKey, addressID int32, to string) (hash []byte, err error) { if to == "" { to = address.ExecAddress(string(execer)) } @@ -129,7 +129,7 @@ func (wallet *Wallet) sendTransaction(payload types.Message, execer []byte, priv } tx.Fee = fee tx.SetExpire(wallet.client.GetConfig(), time.Second*120) - signID := types.EncodeSignID(int32(wallet.SignType), address.GetDefaultAddressID()) + signID := types.EncodeSignID(int32(wallet.SignType), addressID) tx.Sign(signID, priv) reply, err := wallet.sendTx(tx) if err != nil { @@ -203,10 +203,10 @@ func (wallet *Wallet) queryTx(hash []byte) (*types.TransactionDetail, error) { } // SendToAddress 想合约地址转账 -func (wallet *Wallet) SendToAddress(priv crypto.PrivKey, addrto string, amount int64, note string, Istoken bool, tokenSymbol string) (*types.ReplyHash, error) { +func (wallet *Wallet) SendToAddress(priv crypto.PrivKey, addressID int32, addrto string, amount int64, note string, Istoken bool, tokenSymbol string) (*types.ReplyHash, error) { wallet.mtx.Lock() defer wallet.mtx.Unlock() - return wallet.sendToAddress(priv, addrto, amount, note, Istoken, tokenSymbol) + return wallet.sendToAddress(priv, addressID, addrto, amount, note, Istoken, tokenSymbol) } func (wallet *Wallet) createSendToAddress(addrto string, amount int64, note string, Istoken bool, tokenSymbol string) (*types.Transaction, error) { @@ -270,12 +270,12 @@ func (wallet *Wallet) createSendToAddress(addrto string, amount int64, note stri return tx, nil } -func (wallet *Wallet) sendToAddress(priv crypto.PrivKey, addrto string, amount int64, note string, Istoken bool, tokenSymbol string) (*types.ReplyHash, error) { +func (wallet *Wallet) sendToAddress(priv crypto.PrivKey, addressID int32, addrto string, amount int64, note string, Istoken bool, tokenSymbol string) (*types.ReplyHash, error) { tx, err := wallet.createSendToAddress(addrto, amount, note, Istoken, tokenSymbol) if err != nil { return nil, err } - signID := types.EncodeSignID(int32(wallet.SignType), address.GetDefaultAddressID()) + signID := types.EncodeSignID(int32(wallet.SignType), addressID) tx.Sign(signID, priv) reply, err := wallet.api.SendTx(tx) diff --git a/wallet/wallet_proc.go b/wallet/wallet_proc.go index da46d2ead6..d65d8d0fee 100644 --- a/wallet/wallet_proc.go +++ b/wallet/wallet_proc.go @@ -7,6 +7,7 @@ package wallet import ( "encoding/hex" "fmt" + "github.com/33cn/chain33/system/address/eth" "io/ioutil" "os" "strings" @@ -640,7 +641,11 @@ func (wallet *Wallet) ProcSendToAddress(SendToAddress *types.ReqWalletSendToAddr if err != nil { return nil, err } - return wallet.sendToAddress(priv, addrto, amount, note, SendToAddress.IsToken, SendToAddress.TokenSymbol) + addressID := address.GetDefaultAddressID() + if common.IsHex(addrs[0]) { + addressID = eth.ID + } + return wallet.sendToAddress(priv, addressID, addrto, amount, note, SendToAddress.IsToken, SendToAddress.TokenSymbol) } // ProcWalletSetFee 处理设置手续费 diff --git a/wallet/wallet_test.go b/wallet/wallet_test.go index 8871fd63b3..87db971f5c 100644 --- a/wallet/wallet_test.go +++ b/wallet/wallet_test.go @@ -878,16 +878,17 @@ func testSendTx(t *testing.T, wallet *Wallet) { _, err = wallet.GetAllPrivKeys() assert.NoError(t, err) - hash, err := wallet.SendTransaction(&types.ReceiptAccountTransfer{}, []byte("coins"), priv, ToAddr1) + + hash, err := wallet.SendTransaction(&types.ReceiptAccountTransfer{}, []byte("coins"), priv, address.GetDefaultAddressID(), ToAddr1) assert.NoError(t, err) //wallet.WaitTx(hash) wallet.WaitTxs([][]byte{hash}) - hash, err = wallet.SendTransaction(&types.ReceiptAccountTransfer{}, []byte("test"), priv, ToAddr1) + hash, err = wallet.SendTransaction(&types.ReceiptAccountTransfer{}, []byte("test"), priv, address.GetDefaultAddressID(), ToAddr1) assert.NoError(t, err) t.Log(common.ToHex(hash)) - err = wallet.sendTransactionWait(&types.ReceiptAccountTransfer{}, []byte("test"), priv, ToAddr1) + err = wallet.sendTransactionWait(&types.ReceiptAccountTransfer{}, []byte("test"), priv, address.GetDefaultAddressID(), ToAddr1) assert.NoError(t, err) _, err = wallet.getMinerColdAddr(addr)