diff --git a/rpc/api/eth.go b/rpc/api/eth.go index d77bf98035..1883e363c6 100644 --- a/rpc/api/eth.go +++ b/rpc/api/eth.go @@ -6,6 +6,7 @@ import ( "math/big" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/eth" "github.com/ethereum/go-ethereum/rpc/codec" "github.com/ethereum/go-ethereum/rpc/shared" @@ -74,6 +75,7 @@ var ( "eth_hashrate": (*ethApi).Hashrate, "eth_getWork": (*ethApi).GetWork, "eth_submitWork": (*ethApi).SubmitWork, + "eth_resend": (*ethApi).Resend, "eth_pendingTransactions": (*ethApi).PendingTransactions, } ) @@ -553,6 +555,22 @@ func (self *ethApi) SubmitWork(req *shared.Request) (interface{}, error) { return self.xeth.RemoteMining().SubmitWork(args.Nonce, common.HexToHash(args.Digest), common.HexToHash(args.Header)), nil } +func (self *ethApi) Resend(req *shared.Request) (interface{}, error) { + args := new(ResendArgs) + if err := self.codec.Decode(req.Params, &args); err != nil { + return nil, shared.NewDecodeParamError(err.Error()) + } + + ret, err := self.xeth.Transact(args.Tx.From, args.Tx.To, args.Tx.Nonce, args.Tx.Value, args.GasLimit, args.GasPrice, args.Tx.Data) + if err != nil { + return nil, err + } + + self.ethereum.TxPool().RemoveTransactions(types.Transactions{args.Tx.tx}) + + return ret, nil +} + func (self *ethApi) PendingTransactions(req *shared.Request) (interface{}, error) { txs := self.ethereum.TxPool().GetTransactions() diff --git a/rpc/api/eth_args.go b/rpc/api/eth_args.go index 39c003f664..a75fdbdee2 100644 --- a/rpc/api/eth_args.go +++ b/rpc/api/eth_args.go @@ -892,3 +892,53 @@ func newTx(t *types.Transaction) *tx { GasPrice: t.GasPrice().String(), } } + +type ResendArgs struct { + Tx *tx + GasPrice string + GasLimit string +} + +func (args *ResendArgs) UnmarshalJSON(b []byte) (err error) { + var obj []interface{} + if err = json.Unmarshal(b, &obj); err != nil { + return shared.NewDecodeParamError(err.Error()) + } + + if len(obj) < 1 { + return shared.NewInsufficientParamsError(len(obj), 1) + } + + data, err := json.Marshal(obj[0]) + if err != nil { + return shared.NewDecodeParamError("Unable to parse transaction object") + } + + trans := new(tx) + err = json.Unmarshal(data, trans) + if err != nil { + return shared.NewDecodeParamError("Unable to parse transaction object.") + } + + gasLimit, gasPrice := trans.GasLimit, trans.GasPrice + + if len(obj) > 1 && obj[1] != nil { + if gp, ok := obj[1].(string); ok { + gasPrice = gp + } else { + return shared.NewInvalidTypeError("gasPrice", "not a string") + } + } + if len(obj) > 2 && obj[2] != nil { + if gl, ok := obj[2].(string); ok { + gasLimit = gl + } else { + return shared.NewInvalidTypeError("gasLimit", "not a string") + } + } + args.Tx = trans + args.GasPrice = gasPrice + args.GasLimit = gasLimit + + return nil +} diff --git a/rpc/api/eth_js.go b/rpc/api/eth_js.go index 8d0fe8f0a2..4512cc147f 100644 --- a/rpc/api/eth_js.go +++ b/rpc/api/eth_js.go @@ -14,6 +14,13 @@ web3._extend({ params: 2, inputFormatter: [web3._extend.formatters.formatInputString,web3._extend.formatters.formatInputString], outputFormatter: web3._extend.formatters.formatOutputString + }), + new web3._extend.Method({ + name: 'resend', + call: 'eth_resend', + params: 3, + inputFormatter: [function(obj) { return obj; },web3._extend.formatters.formatInputString,web3._extend.formatters.formatInputString], + outputFormatter: web3._extend.formatters.formatOutputString }) ], properties: diff --git a/rpc/api/utils.go b/rpc/api/utils.go index 3d46f78d32..e6a01d3d64 100644 --- a/rpc/api/utils.go +++ b/rpc/api/utils.go @@ -85,6 +85,7 @@ var ( "getWork", "submitWork", "pendingTransactions", + "resend", }, "miner": []string{ "hashrate",