Merge pull request #914 from ethersphere/develop
Signature on arbitrary data using the private keys of an account
This commit is contained in:
commit
0329e05823
@ -29,6 +29,8 @@ const (
|
|||||||
testKey = "e6fab74a43941f82d89cb7faa408e227cdad3153c4720e540e855c19b15e6674"
|
testKey = "e6fab74a43941f82d89cb7faa408e227cdad3153c4720e540e855c19b15e6674"
|
||||||
testAddress = "0x8605cdbbdb6d264aa742e77020dcbc58fcdce182"
|
testAddress = "0x8605cdbbdb6d264aa742e77020dcbc58fcdce182"
|
||||||
testBalance = "10000000000000000000"
|
testBalance = "10000000000000000000"
|
||||||
|
// of empty string
|
||||||
|
testHash = "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -215,6 +217,32 @@ func TestCheckTestAccountBalance(t *testing.T) {
|
|||||||
checkEvalJSON(t, repl, `eth.getBalance(primary)`, `"`+testBalance+`"`)
|
checkEvalJSON(t, repl, `eth.getBalance(primary)`, `"`+testBalance+`"`)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestSignature(t *testing.T) {
|
||||||
|
tmp, repl, ethereum := testJEthRE(t)
|
||||||
|
if err := ethereum.Start(); err != nil {
|
||||||
|
t.Errorf("error starting ethereum: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer ethereum.Stop()
|
||||||
|
defer os.RemoveAll(tmp)
|
||||||
|
|
||||||
|
val, err := repl.re.Run(`eth.sign({from: "` + testAddress + `", data: "` + testHash + `"})`)
|
||||||
|
|
||||||
|
// This is a very preliminary test, lacking actual signature verification
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Error runnig js: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
output := val.String()
|
||||||
|
t.Logf("Output: %v", output)
|
||||||
|
|
||||||
|
regex := regexp.MustCompile(`^0x[0-9a-f]{130}$`)
|
||||||
|
if !regex.MatchString(output) {
|
||||||
|
t.Errorf("Signature is not 65 bytes represented in hexadecimal.")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestContract(t *testing.T) {
|
func TestContract(t *testing.T) {
|
||||||
|
|
||||||
tmp, repl, ethereum := testJEthRE(t)
|
tmp, repl, ethereum := testJEthRE(t)
|
||||||
|
3692
jsre/ethereum_js.go
3692
jsre/ethereum_js.go
File diff suppressed because one or more lines are too long
11
rpc/api.go
11
rpc/api.go
@ -158,6 +158,17 @@ func (api *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) err
|
|||||||
v := api.xethAtStateNum(args.BlockNumber).CodeAtBytes(args.Address)
|
v := api.xethAtStateNum(args.BlockNumber).CodeAtBytes(args.Address)
|
||||||
*reply = newHexData(v)
|
*reply = newHexData(v)
|
||||||
|
|
||||||
|
case "eth_sign":
|
||||||
|
args := new(NewSigArgs)
|
||||||
|
if err := json.Unmarshal(req.Params, &args); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
v, err := api.xeth().Sign(args.From, args.Data, false)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
*reply = v
|
||||||
|
|
||||||
case "eth_sendTransaction", "eth_transact":
|
case "eth_sendTransaction", "eth_transact":
|
||||||
args := new(NewTxArgs)
|
args := new(NewTxArgs)
|
||||||
if err := json.Unmarshal(req.Params, &args); err != nil {
|
if err := json.Unmarshal(req.Params, &args); err != nil {
|
||||||
|
40
rpc/args.go
40
rpc/args.go
@ -166,6 +166,46 @@ type NewTxArgs struct {
|
|||||||
BlockNumber int64
|
BlockNumber int64
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type NewSigArgs struct {
|
||||||
|
From string
|
||||||
|
Data string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (args *NewSigArgs) UnmarshalJSON(b []byte) (err error) {
|
||||||
|
var obj []json.RawMessage
|
||||||
|
var ext struct {
|
||||||
|
From string
|
||||||
|
Data string
|
||||||
|
}
|
||||||
|
|
||||||
|
// Decode byte slice to array of RawMessages
|
||||||
|
if err := json.Unmarshal(b, &obj); err != nil {
|
||||||
|
return NewDecodeParamError(err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for sufficient params
|
||||||
|
if len(obj) < 1 {
|
||||||
|
return NewInsufficientParamsError(len(obj), 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Decode 0th RawMessage to temporary struct
|
||||||
|
if err := json.Unmarshal(obj[0], &ext); err != nil {
|
||||||
|
return NewDecodeParamError(err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(ext.From) == 0 {
|
||||||
|
return NewValidationError("from", "is required")
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(ext.Data) == 0 {
|
||||||
|
return NewValidationError("data", "is required")
|
||||||
|
}
|
||||||
|
|
||||||
|
args.From = ext.From
|
||||||
|
args.Data = ext.Data
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (args *NewTxArgs) UnmarshalJSON(b []byte) (err error) {
|
func (args *NewTxArgs) UnmarshalJSON(b []byte) (err error) {
|
||||||
var obj []json.RawMessage
|
var obj []json.RawMessage
|
||||||
var ext struct {
|
var ext struct {
|
||||||
|
@ -3,7 +3,6 @@ package rpc
|
|||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/jsre"
|
"github.com/ethereum/go-ethereum/jsre"
|
||||||
"github.com/robertkrimen/otto"
|
"github.com/robertkrimen/otto"
|
||||||
)
|
)
|
||||||
@ -36,7 +35,6 @@ func (self *Jeth) Send(call otto.FunctionCall) (response otto.Value) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
jsonreq, err := json.Marshal(reqif)
|
jsonreq, err := json.Marshal(reqif)
|
||||||
|
|
||||||
var reqs []RpcRequest
|
var reqs []RpcRequest
|
||||||
batch := true
|
batch := true
|
||||||
err = json.Unmarshal(jsonreq, &reqs)
|
err = json.Unmarshal(jsonreq, &reqs)
|
||||||
|
43
xeth/xeth.go
43
xeth/xeth.go
@ -815,6 +815,35 @@ func (self *XEth) ConfirmTransaction(tx string) bool {
|
|||||||
return self.frontend.ConfirmTransaction(tx)
|
return self.frontend.ConfirmTransaction(tx)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (self *XEth) doSign(from common.Address, hash common.Hash, didUnlock bool) ([]byte, error) {
|
||||||
|
sig, err := self.backend.AccountManager().Sign(accounts.Account{Address: from.Bytes()}, hash.Bytes())
|
||||||
|
if err == accounts.ErrLocked {
|
||||||
|
if didUnlock {
|
||||||
|
return nil, fmt.Errorf("signer account still locked after successful unlock")
|
||||||
|
}
|
||||||
|
if !self.frontend.UnlockAccount(from.Bytes()) {
|
||||||
|
return nil, fmt.Errorf("could not unlock signer account")
|
||||||
|
}
|
||||||
|
// retry signing, the account should now be unlocked.
|
||||||
|
return self.doSign(from, hash, true)
|
||||||
|
} else if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return sig, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *XEth) Sign(fromStr, hashStr string, didUnlock bool) (string, error) {
|
||||||
|
var (
|
||||||
|
from = common.HexToAddress(fromStr)
|
||||||
|
hash = common.HexToHash(hashStr)
|
||||||
|
)
|
||||||
|
sig, err := self.doSign(from, hash, didUnlock)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return common.ToHex(sig), nil
|
||||||
|
}
|
||||||
|
|
||||||
func (self *XEth) Transact(fromStr, toStr, nonceStr, valueStr, gasStr, gasPriceStr, codeStr string) (string, error) {
|
func (self *XEth) Transact(fromStr, toStr, nonceStr, valueStr, gasStr, gasPriceStr, codeStr string) (string, error) {
|
||||||
|
|
||||||
// this minimalistic recoding is enough (works for natspec.js)
|
// this minimalistic recoding is enough (works for natspec.js)
|
||||||
@ -907,17 +936,9 @@ func (self *XEth) Transact(fromStr, toStr, nonceStr, valueStr, gasStr, gasPriceS
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (self *XEth) sign(tx *types.Transaction, from common.Address, didUnlock bool) error {
|
func (self *XEth) sign(tx *types.Transaction, from common.Address, didUnlock bool) error {
|
||||||
sig, err := self.backend.AccountManager().Sign(accounts.Account{Address: from.Bytes()}, tx.Hash().Bytes())
|
hash := tx.Hash()
|
||||||
if err == accounts.ErrLocked {
|
sig, err := self.doSign(from, hash, didUnlock)
|
||||||
if didUnlock {
|
if err != nil {
|
||||||
return fmt.Errorf("sender account still locked after successful unlock")
|
|
||||||
}
|
|
||||||
if !self.frontend.UnlockAccount(from.Bytes()) {
|
|
||||||
return fmt.Errorf("could not unlock sender account")
|
|
||||||
}
|
|
||||||
// retry signing, the account should now be unlocked.
|
|
||||||
return self.sign(tx, from, true)
|
|
||||||
} else if err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
tx.SetSignatureValues(sig)
|
tx.SetSignatureValues(sig)
|
||||||
|
Loading…
Reference in New Issue
Block a user