forked from cerc-io/plugeth
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"
|
||||
testAddress = "0x8605cdbbdb6d264aa742e77020dcbc58fcdce182"
|
||||
testBalance = "10000000000000000000"
|
||||
// of empty string
|
||||
testHash = "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470"
|
||||
)
|
||||
|
||||
var (
|
||||
@ -215,6 +217,32 @@ func TestCheckTestAccountBalance(t *testing.T) {
|
||||
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) {
|
||||
|
||||
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)
|
||||
*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":
|
||||
args := new(NewTxArgs)
|
||||
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
|
||||
}
|
||||
|
||||
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) {
|
||||
var obj []json.RawMessage
|
||||
var ext struct {
|
||||
|
@ -3,7 +3,6 @@ package rpc
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"github.com/ethereum/go-ethereum/jsre"
|
||||
"github.com/robertkrimen/otto"
|
||||
)
|
||||
@ -36,7 +35,6 @@ func (self *Jeth) Send(call otto.FunctionCall) (response otto.Value) {
|
||||
}
|
||||
|
||||
jsonreq, err := json.Marshal(reqif)
|
||||
|
||||
var reqs []RpcRequest
|
||||
batch := true
|
||||
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)
|
||||
}
|
||||
|
||||
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) {
|
||||
|
||||
// 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 {
|
||||
sig, err := self.backend.AccountManager().Sign(accounts.Account{Address: from.Bytes()}, tx.Hash().Bytes())
|
||||
if err == accounts.ErrLocked {
|
||||
if didUnlock {
|
||||
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 {
|
||||
hash := tx.Hash()
|
||||
sig, err := self.doSign(from, hash, didUnlock)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
tx.SetSignatureValues(sig)
|
||||
|
Loading…
Reference in New Issue
Block a user