Skip to content

Commit 6ea05f5

Browse files
committed
rpc/api, xeth: added signTransaction method
SignTransaction creates a transaction but does submit it to the network. SignTransaction returns a structure which includes the transaction object details as well as the RLP encoded transaction that could possibly be submitted by the SendRawTransaction method.
1 parent 9422eec commit 6ea05f5

File tree

3 files changed

+115
-7
lines changed

3 files changed

+115
-7
lines changed

rpc/api/eth.go

Lines changed: 44 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import (
2626
"github.com/ethereum/go-ethereum/common"
2727
"github.com/ethereum/go-ethereum/common/natspec"
2828
"github.com/ethereum/go-ethereum/eth"
29+
"github.com/ethereum/go-ethereum/rlp"
2930
"github.com/ethereum/go-ethereum/rpc/codec"
3031
"github.com/ethereum/go-ethereum/rpc/shared"
3132
"github.com/ethereum/go-ethereum/xeth"
@@ -70,8 +71,10 @@ var (
7071
"eth_getCode": (*ethApi).GetData,
7172
"eth_getNatSpec": (*ethApi).GetNatSpec,
7273
"eth_sign": (*ethApi).Sign,
73-
"eth_sendRawTransaction": (*ethApi).SendRawTransaction,
74+
"eth_sendRawTransaction": (*ethApi).SubmitTransaction,
75+
"eth_submitTransaction": (*ethApi).SubmitTransaction,
7476
"eth_sendTransaction": (*ethApi).SendTransaction,
77+
"eth_signTransaction": (*ethApi).SignTransaction,
7578
"eth_transact": (*ethApi).SendTransaction,
7679
"eth_estimateGas": (*ethApi).EstimateGas,
7780
"eth_call": (*ethApi).Call,
@@ -285,7 +288,7 @@ func (self *ethApi) Sign(req *shared.Request) (interface{}, error) {
285288
return v, nil
286289
}
287290

288-
func (self *ethApi) SendRawTransaction(req *shared.Request) (interface{}, error) {
291+
func (self *ethApi) SubmitTransaction(req *shared.Request) (interface{}, error) {
289292
args := new(NewDataArgs)
290293
if err := self.codec.Decode(req.Params, &args); err != nil {
291294
return nil, shared.NewDecodeParamError(err.Error())
@@ -298,6 +301,45 @@ func (self *ethApi) SendRawTransaction(req *shared.Request) (interface{}, error)
298301
return v, nil
299302
}
300303

304+
// JsonTransaction is returned as response by the JSON RPC. It contains the
305+
// signed RLP encoded transaction as Raw and the signed transaction object as Tx.
306+
type JsonTransaction struct {
307+
Raw string `json:"raw"`
308+
Tx *tx `json:"tx"`
309+
}
310+
311+
func (self *ethApi) SignTransaction(req *shared.Request) (interface{}, error) {
312+
args := new(NewTxArgs)
313+
if err := self.codec.Decode(req.Params, &args); err != nil {
314+
return nil, shared.NewDecodeParamError(err.Error())
315+
}
316+
317+
// nonce may be nil ("guess" mode)
318+
var nonce string
319+
if args.Nonce != nil {
320+
nonce = args.Nonce.String()
321+
}
322+
323+
var gas, price string
324+
if args.Gas != nil {
325+
gas = args.Gas.String()
326+
}
327+
if args.GasPrice != nil {
328+
price = args.GasPrice.String()
329+
}
330+
tx, err := self.xeth.SignTransaction(args.From, args.To, nonce, args.Value.String(), gas, price, args.Data)
331+
if err != nil {
332+
return nil, err
333+
}
334+
335+
data, err := rlp.EncodeToBytes(tx)
336+
if err != nil {
337+
return nil, err
338+
}
339+
340+
return JsonTransaction{"0x" + common.Bytes2Hex(data), newTx(tx)}, nil
341+
}
342+
301343
func (self *ethApi) SendTransaction(req *shared.Request) (interface{}, error) {
302344
args := new(NewTxArgs)
303345
if err := self.codec.Decode(req.Params, &args); err != nil {

rpc/api/eth_js.go

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,11 +36,23 @@ web3._extend({
3636
params: 3,
3737
inputFormatter: [web3._extend.formatters.inputTransactionFormatter, web3._extend.utils.fromDecimal, web3._extend.utils.fromDecimal]
3838
}),
39-
new web3._extend.Method({
40-
name: 'getNatSpec',
41-
call: 'eth_getNatSpec',
42-
params: 1,
43-
inputFormatter: [web3._extend.formatters.inputTransactionFormatter]
39+
new web3._extend.Method({
40+
name: 'getNatSpec',
41+
call: 'eth_getNatSpec',
42+
params: 1,
43+
inputFormatter: [web3._extend.formatters.inputTransactionFormatter]
44+
}),
45+
new web3._extend.Method({
46+
name: 'signTransaction',
47+
call: 'eth_signTransaction',
48+
params: 1,
49+
inputFormatter: [web3._extend.formatters.inputTransactionFormatter]
50+
}),
51+
new web3._extend.Method({
52+
name: 'submitTransaction',
53+
call: 'eth_submitTransaction',
54+
params: 1,
55+
inputFormatter: [web3._extend.formatters.inputTransactionFormatter]
4456
})
4557
],
4658
properties:

xeth/xeth.go

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -912,6 +912,60 @@ func (self *XEth) Frontend() Frontend {
912912
return self.frontend
913913
}
914914

915+
func (self *XEth) SignTransaction(fromStr, toStr, nonceStr, valueStr, gasStr, gasPriceStr, codeStr string) (*types.Transaction, error) {
916+
if len(toStr) > 0 && toStr != "0x" && !isAddress(toStr) {
917+
return nil, errors.New("Invalid address")
918+
}
919+
920+
var (
921+
from = common.HexToAddress(fromStr)
922+
to = common.HexToAddress(toStr)
923+
value = common.Big(valueStr)
924+
gas *big.Int
925+
price *big.Int
926+
data []byte
927+
contractCreation bool
928+
)
929+
930+
if len(gasStr) == 0 {
931+
gas = DefaultGas()
932+
} else {
933+
gas = common.Big(gasStr)
934+
}
935+
936+
if len(gasPriceStr) == 0 {
937+
price = self.DefaultGasPrice()
938+
} else {
939+
price = common.Big(gasPriceStr)
940+
}
941+
942+
data = common.FromHex(codeStr)
943+
if len(toStr) == 0 {
944+
contractCreation = true
945+
}
946+
947+
var nonce uint64
948+
if len(nonceStr) != 0 {
949+
nonce = common.Big(nonceStr).Uint64()
950+
} else {
951+
state := self.backend.TxPool().State()
952+
nonce = state.GetNonce(from)
953+
}
954+
var tx *types.Transaction
955+
if contractCreation {
956+
tx = types.NewContractCreation(nonce, value, gas, price, data)
957+
} else {
958+
tx = types.NewTransaction(nonce, to, value, gas, price, data)
959+
}
960+
961+
signed, err := self.sign(tx, from, false)
962+
if err != nil {
963+
return nil, err
964+
}
965+
966+
return signed, nil
967+
}
968+
915969
func (self *XEth) Transact(fromStr, toStr, nonceStr, valueStr, gasStr, gasPriceStr, codeStr string) (string, error) {
916970

917971
// this minimalistic recoding is enough (works for natspec.js)

0 commit comments

Comments
 (0)