mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-18 18:02:24 +00:00
signer: refactoring + documentation
This commit is contained in:
parent
a8e68b9cc3
commit
99dd0a1b58
12 changed files with 175 additions and 122 deletions
|
|
@ -174,9 +174,9 @@ None
|
||||||
Signs a transactions and responds with the signed transaction in RLP encoded form.
|
Signs a transactions and responds with the signed transaction in RLP encoded form.
|
||||||
|
|
||||||
#### Arguments
|
#### Arguments
|
||||||
1. from [address]: account to send the transaction from
|
|
||||||
2. transaction object:
|
2. transaction object:
|
||||||
- `to` [address]: receiver account
|
- `from` [address]: account to send the transaction from
|
||||||
|
- `to` [address]: receiver account. If omitted or `0x`, will cause contract creation.
|
||||||
- `gas` [number]: maximum amount of gas to burn
|
- `gas` [number]: maximum amount of gas to burn
|
||||||
- `gasPrice` [number]: gas price
|
- `gasPrice` [number]: gas price
|
||||||
- `value` [number:optional]: amount of Wei to send with the transaction
|
- `value` [number:optional]: amount of Wei to send with the transaction
|
||||||
|
|
@ -196,8 +196,8 @@ None
|
||||||
"jsonrpc": "2.0",
|
"jsonrpc": "2.0",
|
||||||
"method": "account_signTransaction",
|
"method": "account_signTransaction",
|
||||||
"params": [
|
"params": [
|
||||||
"0x1923f626bb8dc025849e00f99c25fe2b2f7fb0db",
|
|
||||||
{
|
{
|
||||||
|
"from": "0x1923f626bb8dc025849e00f99c25fe2b2f7fb0db",
|
||||||
"gas": "0x55555",
|
"gas": "0x55555",
|
||||||
"gasPrice": "0x1234",
|
"gasPrice": "0x1234",
|
||||||
"input": "0xabcd",
|
"input": "0xabcd",
|
||||||
|
|
@ -209,11 +209,64 @@ None
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
"id": 2,
|
|
||||||
"jsonrpc": "2.0",
|
"jsonrpc": "2.0",
|
||||||
"result": "0xf86480821234830555559407a565b7ed7d7a678680a4c162885bedbb695fe0821234802ea028f9ebeff90732eae45692a11c4ca2ef7f631a0a25bf8763d093e770c4ec464aa01fae77b24617913e718b989be78bc1aabb2fed3f2d4e3b93bd36759f1b5b4904"
|
"id": 67,
|
||||||
|
"error": {
|
||||||
|
"code": -32000,
|
||||||
|
"message": "Request denied"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
#### Sample call with ABI-data
|
||||||
|
|
||||||
|
|
||||||
|
```
|
||||||
|
{
|
||||||
|
"jsonrpc": "2.0",
|
||||||
|
"method": "account_signTransaction",
|
||||||
|
"params": [
|
||||||
|
{
|
||||||
|
"from": "0x694267f14675d7e1b9494fd8d72fefe1755710fa",
|
||||||
|
"gas": "0x333",
|
||||||
|
"gasPrice": "0x1",
|
||||||
|
"nonce": "0x0",
|
||||||
|
"to": "0x07a565b7ed7d7a678680a4c162885bedbb695fe0",
|
||||||
|
"value": "0x0",
|
||||||
|
"data": "0x4401a6e40000000000000000000000000000000000000000000000000000000000000012"
|
||||||
|
},
|
||||||
|
"safeSend(address)"
|
||||||
|
],
|
||||||
|
"id": 67
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
"jsonrpc": "2.0",
|
||||||
|
"id": 67,
|
||||||
|
"result": {
|
||||||
|
"raw": "0xf88380018203339407a565b7ed7d7a678680a4c162885bedbb695fe080a44401a6e4000000000000000000000000000000000000000000000000000000000000001226a0223a7c9bcf5531c99be5ea7082183816eb20cfe0bbc322e97cc5c7f71ab8b20ea02aadee6b34b45bb15bc42d9c09de4a6754e7000908da72d48cc7704971491663",
|
||||||
|
"tx": {
|
||||||
|
"nonce": "0x0",
|
||||||
|
"gasPrice": "0x1",
|
||||||
|
"gas": "0x333",
|
||||||
|
"to": "0x07a565b7ed7d7a678680a4c162885bedbb695fe0",
|
||||||
|
"value": "0x0",
|
||||||
|
"input": "0x4401a6e40000000000000000000000000000000000000000000000000000000000000012",
|
||||||
|
"v": "0x26",
|
||||||
|
"r": "0x223a7c9bcf5531c99be5ea7082183816eb20cfe0bbc322e97cc5c7f71ab8b20e",
|
||||||
|
"s": "0x2aadee6b34b45bb15bc42d9c09de4a6754e7000908da72d48cc7704971491663",
|
||||||
|
"hash": "0xeba2df809e7a612a0a0d444ccfa5c839624bdc00dd29e3340d46df3870f8a30e"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Bash example:
|
||||||
|
```bash
|
||||||
|
#curl -H "Content-Type: application/json" -X POST --data '{"jsonrpc":"2.0","method":"account_signTransaction","params":[{"from":"0x694267f14675d7e1b9494fd8d72fefe1755710fa","gas":"0x333","gasPrice":"0x1","nonce":"0x0","to":"0x07a565b7ed7d7a678680a4c162885bedbb695fe0", "value":"0x0", "data":"0x4401a6e40000000000000000000000000000000000000000000000000000000000000012"},"safeSend(address)"],"id":67}' http://localhost:8550/
|
||||||
|
|
||||||
|
{"jsonrpc":"2.0","id":67,"result":{"raw":"0xf88380018203339407a565b7ed7d7a678680a4c162885bedbb695fe080a44401a6e4000000000000000000000000000000000000000000000000000000000000001226a0223a7c9bcf5531c99be5ea7082183816eb20cfe0bbc322e97cc5c7f71ab8b20ea02aadee6b34b45bb15bc42d9c09de4a6754e7000908da72d48cc7704971491663","tx":{"nonce":"0x0","gasPrice":"0x1","gas":"0x333","to":"0x07a565b7ed7d7a678680a4c162885bedbb695fe0","value":"0x0","input":"0x4401a6e40000000000000000000000000000000000000000000000000000000000000012","v":"0x26","r":"0x223a7c9bcf5531c99be5ea7082183816eb20cfe0bbc322e97cc5c7f71ab8b20e","s":"0x2aadee6b34b45bb15bc42d9c09de4a6754e7000908da72d48cc7704971491663","hash":"0xeba2df809e7a612a0a0d444ccfa5c839624bdc00dd29e3340d46df3870f8a30e"}}}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
### account_sign
|
### account_sign
|
||||||
|
|
||||||
|
|
@ -395,7 +448,8 @@ By starting the signer with the switch `--stdio-ui-test`, the signer will invoke
|
||||||
denials. This can be used during development to ensure that the API is (at least somewhat) correctly implemented.
|
denials. This can be used during development to ensure that the API is (at least somewhat) correctly implemented.
|
||||||
See `pythonsigner`, which can be invoked via `python3 pythonsigner.py test` to perform the 'denial-handshake-test'.
|
See `pythonsigner`, which can be invoked via `python3 pythonsigner.py test` to perform the 'denial-handshake-test'.
|
||||||
|
|
||||||
**work in progress**
|
All methods in this API uses object-based parameters, so that there can be no mixups of parameters: each piece of data is accessed by key.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### ApproveTx
|
### ApproveTx
|
||||||
|
|
@ -560,6 +614,15 @@ The UI should show the info to the user. Does not expect response.
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### OnApproved
|
||||||
|
|
||||||
|
`OnApprovedTx` is called when a transaction has been approved and signed. The call contains the return value that will be sent to the external caller. The return value from this method is ignored - the reason for having this callback is to allow the ruleset to keep track of approved transactions.
|
||||||
|
|
||||||
|
When implementing rate-limited rules, this callback should be used.
|
||||||
|
|
||||||
|
TLDR; Use this method to keep track of signed transactions, instead of using the data in `ApproveTx`.
|
||||||
|
|
||||||
|
|
||||||
### Rules for UI apis
|
### Rules for UI apis
|
||||||
|
|
||||||
A UI should conform to the following rules.
|
A UI should conform to the following rules.
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@
|
||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
|
// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
package signer
|
package core
|
||||||
|
|
||||||
import (
|
import (
|
||||||
// "bytes"
|
// "bytes"
|
||||||
|
|
@ -157,25 +157,25 @@ func MethodSelectorToAbi(selector string) ([]byte, error) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type abiDb struct {
|
type AbiDb struct {
|
||||||
db map[string]string
|
db map[string]string
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewAbiDBFromFile loads signature database from file, and
|
// NewAbiDBFromFile loads signature database from file, and
|
||||||
// errors if the file is not valid json. Does no other validation of contents
|
// errors if the file is not valid json. Does no other validation of contents
|
||||||
func NewAbiDBFromFile(path string) (*abiDb, error) {
|
func NewAbiDBFromFile(path string) (*AbiDb, error) {
|
||||||
raw, err := ioutil.ReadFile(path)
|
raw, err := ioutil.ReadFile(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
db := new(abiDb)
|
db := new(AbiDb)
|
||||||
json.Unmarshal(raw, &db.db)
|
json.Unmarshal(raw, &db.db)
|
||||||
return db, nil
|
return db, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// LookupMethodSelector checks the given 4byte-sequence against the known ABI methods.
|
// LookupMethodSelector checks the given 4byte-sequence against the known ABI methods.
|
||||||
// OBS: This method does not validate the match, it's assumed the caller will do so
|
// OBS: This method does not validate the match, it's assumed the caller will do so
|
||||||
func (db *abiDb) LookupMethodSelector(id []byte) (string, error) {
|
func (db *AbiDb) LookupMethodSelector(id []byte) (string, error) {
|
||||||
if len(id) != 4 {
|
if len(id) != 4 {
|
||||||
return "", fmt.Errorf("Expected 4-byte id, got %d", len(id))
|
return "", fmt.Errorf("Expected 4-byte id, got %d", len(id))
|
||||||
}
|
}
|
||||||
|
|
@ -185,6 +185,6 @@ func (db *abiDb) LookupMethodSelector(id []byte) (string, error) {
|
||||||
}
|
}
|
||||||
return "", fmt.Errorf("Signature %v not found", sig)
|
return "", fmt.Errorf("Signature %v not found", sig)
|
||||||
}
|
}
|
||||||
func (db *abiDb) Size() int {
|
func (db *AbiDb) Size() int {
|
||||||
return len(db.db)
|
return len(db.db)
|
||||||
}
|
}
|
||||||
|
|
@ -14,7 +14,7 @@
|
||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
|
// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
package signer
|
package core
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
@ -176,13 +176,13 @@ func TestCalldataDecoding(t *testing.T) {
|
||||||
|
|
||||||
func TestSelectorUnmarshalling(t *testing.T) {
|
func TestSelectorUnmarshalling(t *testing.T) {
|
||||||
var (
|
var (
|
||||||
db *abiDb
|
db *AbiDb
|
||||||
err error
|
err error
|
||||||
abistring []byte
|
abistring []byte
|
||||||
abistruct abi.ABI
|
abistruct abi.ABI
|
||||||
)
|
)
|
||||||
|
|
||||||
db, err = NewAbiDBFromFile("4byte.json")
|
db, err = NewAbiDBFromFile("../4byte.json")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
@ -14,7 +14,7 @@
|
||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
|
// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
package signer
|
package core
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
@ -69,7 +69,7 @@ type SignerUI interface {
|
||||||
// ApproveImport prompt the user for confirmation to import Account json
|
// ApproveImport prompt the user for confirmation to import Account json
|
||||||
ApproveImport(request *ImportRequest) (ImportResponse, error)
|
ApproveImport(request *ImportRequest) (ImportResponse, error)
|
||||||
// ApproveListing prompt the user for confirmation to list accounts
|
// ApproveListing prompt the user for confirmation to list accounts
|
||||||
// the list of accounts to list can be modified by the ui
|
// the list of accounts to list can be modified by the UI
|
||||||
ApproveListing(request *ListRequest) (ListResponse, error)
|
ApproveListing(request *ListRequest) (ListResponse, error)
|
||||||
// ApproveNewAccount prompt the user for confirmation to create new Account, and reveal to caller
|
// ApproveNewAccount prompt the user for confirmation to create new Account, and reveal to caller
|
||||||
ApproveNewAccount(request *NewAccountRequest) (NewAccountResponse, error)
|
ApproveNewAccount(request *NewAccountRequest) (NewAccountResponse, error)
|
||||||
|
|
@ -86,8 +86,8 @@ type SignerUI interface {
|
||||||
type SignerAPI struct {
|
type SignerAPI struct {
|
||||||
chainID *big.Int
|
chainID *big.Int
|
||||||
am *accounts.Manager
|
am *accounts.Manager
|
||||||
ui SignerUI
|
UI SignerUI
|
||||||
abidb abiDb
|
abidb AbiDb
|
||||||
}
|
}
|
||||||
|
|
||||||
// Metadata about a request
|
// Metadata about a request
|
||||||
|
|
@ -201,7 +201,7 @@ func (ew errorWrapper) String() string {
|
||||||
// key that is generated when a new Account is created.
|
// key that is generated when a new Account is created.
|
||||||
// noUSB disables USB support that is required to support hardware devices such as
|
// noUSB disables USB support that is required to support hardware devices such as
|
||||||
// ledger and trezor.
|
// ledger and trezor.
|
||||||
func NewSignerAPI(chainID int64, ksLocation string, noUSB bool, ui SignerUI, abidb *abiDb, lightKDF bool) *SignerAPI {
|
func NewSignerAPI(chainID int64, ksLocation string, noUSB bool, ui SignerUI, abidb *AbiDb, lightKDF bool) *SignerAPI {
|
||||||
var (
|
var (
|
||||||
backends []accounts.Backend
|
backends []accounts.Backend
|
||||||
n, p = keystore.StandardScryptN, keystore.StandardScryptP
|
n, p = keystore.StandardScryptN, keystore.StandardScryptP
|
||||||
|
|
@ -242,7 +242,7 @@ func (api *SignerAPI) List(ctx context.Context) (Accounts, error) {
|
||||||
accs = append(accs, acc)
|
accs = append(accs, acc)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
result, err := api.ui.ApproveListing(&ListRequest{Accounts: accs, Meta: MetadataFromContext(ctx)})
|
result, err := api.UI.ApproveListing(&ListRequest{Accounts: accs, Meta: MetadataFromContext(ctx)})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
@ -261,7 +261,7 @@ func (api *SignerAPI) New(ctx context.Context) (accounts.Account, error) {
|
||||||
if len(be) == 0 {
|
if len(be) == 0 {
|
||||||
return accounts.Account{}, errors.New("password based accounts not supported")
|
return accounts.Account{}, errors.New("password based accounts not supported")
|
||||||
}
|
}
|
||||||
resp, err := api.ui.ApproveNewAccount(&NewAccountRequest{MetadataFromContext(ctx)})
|
resp, err := api.UI.ApproveNewAccount(&NewAccountRequest{MetadataFromContext(ctx)})
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return accounts.Account{}, err
|
return accounts.Account{}, err
|
||||||
|
|
@ -277,33 +277,25 @@ func (api *SignerAPI) New(ctx context.Context) (accounts.Account, error) {
|
||||||
// UI-modifications to requests
|
// UI-modifications to requests
|
||||||
func logDiff(original *SignTxRequest, new *SignTxResponse) bool {
|
func logDiff(original *SignTxRequest, new *SignTxResponse) bool {
|
||||||
modified := false
|
modified := false
|
||||||
|
|
||||||
if f0, f1 := original.Transaction.From, new.Transaction.From; !reflect.DeepEqual(f0, f1) {
|
if f0, f1 := original.Transaction.From, new.Transaction.From; !reflect.DeepEqual(f0, f1) {
|
||||||
log.Info("Sender-account changed by UI", "was", f0, "is", f1)
|
log.Info("Sender-account changed by UI", "was", f0, "is", f1)
|
||||||
modified = true
|
modified = true
|
||||||
}
|
}
|
||||||
|
|
||||||
if t0, t1 := original.Transaction.To, new.Transaction.To; !reflect.DeepEqual(t0, t1) {
|
if t0, t1 := original.Transaction.To, new.Transaction.To; !reflect.DeepEqual(t0, t1) {
|
||||||
log.Info("Recipient-account changed by UI", "was", t0, "is", t1)
|
log.Info("Recipient-account changed by UI", "was", t0, "is", t1)
|
||||||
modified = true
|
modified = true
|
||||||
}
|
}
|
||||||
if g0, g1 := (*big.Int)(original.Transaction.Gas), (*big.Int)(new.Transaction.Gas); g0 != g1 {
|
if g0, g1 := big.Int(original.Transaction.Gas), big.Int(new.Transaction.Gas); g0.Cmp(&g1) != 0 {
|
||||||
if g0 == nil || g1 == nil || g0.Cmp(g1) != 0 {
|
modified = true
|
||||||
modified = true
|
log.Info("Gas changed by UI", "was", g0, "is", g1)
|
||||||
log.Info("Gas changed by UI", "was", g0, "is", g1)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if g0, g1 := (*big.Int)(original.Transaction.GasPrice), (*big.Int)(new.Transaction.GasPrice); g0 != g1 {
|
if g0, g1 := big.Int(original.Transaction.GasPrice), big.Int(new.Transaction.GasPrice); g0.Cmp(&g1) != 0 {
|
||||||
if g0 == nil || g1 == nil || g0.Cmp(g1) != 0 {
|
modified = true
|
||||||
modified = true
|
log.Info("GasPrice changed by UI", "was", g0, "is", g1)
|
||||||
log.Info("GasPrice changed by UI", "was", g0, "is", g1)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if v0, v1 := (*big.Int)(original.Transaction.Value), (*big.Int)(new.Transaction.Value); v0 != v1 {
|
if v0, v1 := big.Int(original.Transaction.Value), big.Int(new.Transaction.Value); v0.Cmp(&v1) != 0 {
|
||||||
if v0 == nil || v1 == nil || v0.Cmp(v1) != 0 {
|
modified = true
|
||||||
modified = true
|
log.Info("Value changed by UI", "was", v0, "is", v1)
|
||||||
log.Info("Value changed by UI", "was", v0, "is", v1)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if d0, d1 := original.Transaction.Data, new.Transaction.Data; d0 != d1 {
|
if d0, d1 := original.Transaction.Data, new.Transaction.Data; d0 != d1 {
|
||||||
d0s := ""
|
d0s := ""
|
||||||
|
|
@ -320,11 +312,8 @@ func logDiff(original *SignTxRequest, new *SignTxResponse) bool {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if n0, n1 := original.Transaction.Nonce, new.Transaction.Nonce; n0 != n1 {
|
if n0, n1 := original.Transaction.Nonce, new.Transaction.Nonce; n0 != n1 {
|
||||||
|
modified = true
|
||||||
if n0 == nil || n1 == nil || (*n0) != (*n1) {
|
log.Info("Nonce changed by UI", "was", n0, "is", n1)
|
||||||
modified = true
|
|
||||||
log.Info("Nonce changed by UI", "was", n0, "is", n1)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return modified
|
return modified
|
||||||
}
|
}
|
||||||
|
|
@ -386,12 +375,12 @@ func (api *SignerAPI) SignTransaction(ctx context.Context, args SendTxArgs, meth
|
||||||
*args.Input = nil
|
*args.Input = nil
|
||||||
}
|
}
|
||||||
req := SignTxRequest{
|
req := SignTxRequest{
|
||||||
Transaction: args,
|
Transaction: args,
|
||||||
Meta: MetadataFromContext(ctx),
|
Meta: MetadataFromContext(ctx),
|
||||||
Callinfo:api.determineCallInfo(data, methodSelector),
|
Callinfo: api.determineCallInfo(data, methodSelector),
|
||||||
}
|
}
|
||||||
// Process approval
|
// Process approval
|
||||||
result, err = api.ui.ApproveTx(&req)
|
result, err = api.UI.ApproveTx(&req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
@ -415,7 +404,7 @@ func (api *SignerAPI) SignTransaction(ctx context.Context, args SendTxArgs, meth
|
||||||
// The one to sign is the one that was returned from the UI
|
// The one to sign is the one that was returned from the UI
|
||||||
signedTx, err := wallet.SignTxWithPassphrase(acc, result.Password, unsignedTx, api.chainID)
|
signedTx, err := wallet.SignTxWithPassphrase(acc, result.Password, unsignedTx, api.chainID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
api.ui.ShowError(err.Error())
|
api.UI.ShowError(err.Error())
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -423,7 +412,7 @@ func (api *SignerAPI) SignTransaction(ctx context.Context, args SendTxArgs, meth
|
||||||
response := ethapi.SignTransactionResult{rlpdata, signedTx}
|
response := ethapi.SignTransactionResult{rlpdata, signedTx}
|
||||||
|
|
||||||
// Finally, send the signed tx to the UI
|
// Finally, send the signed tx to the UI
|
||||||
api.ui.OnApprovedTx(response)
|
api.UI.OnApprovedTx(response)
|
||||||
// ...and to the external caller
|
// ...and to the external caller
|
||||||
return &response, nil
|
return &response, nil
|
||||||
|
|
||||||
|
|
@ -443,7 +432,7 @@ func (api *SignerAPI) Sign(ctx context.Context, addr common.MixedcaseAddress, da
|
||||||
// We make the request prior to looking up if we actually have the account, to prevent
|
// We make the request prior to looking up if we actually have the account, to prevent
|
||||||
// account-enumeration via the API
|
// account-enumeration via the API
|
||||||
req := &SignDataRequest{Address: addr, Rawdata: data, Message: msg, Hash: sighash, Meta: MetadataFromContext(ctx)}
|
req := &SignDataRequest{Address: addr, Rawdata: data, Message: msg, Hash: sighash, Meta: MetadataFromContext(ctx)}
|
||||||
res, err := api.ui.ApproveSignData(req)
|
res, err := api.UI.ApproveSignData(req)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
@ -460,7 +449,7 @@ func (api *SignerAPI) Sign(ctx context.Context, addr common.MixedcaseAddress, da
|
||||||
// Assemble sign the data with the wallet
|
// Assemble sign the data with the wallet
|
||||||
signature, err := wallet.SignHashWithPassphrase(account, res.Password, sighash)
|
signature, err := wallet.SignHashWithPassphrase(account, res.Password, sighash)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
api.ui.ShowError(err.Error())
|
api.UI.ShowError(err.Error())
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
signature[64] += 27 // Transform V from 0/1 to 27/28 according to the yellow paper
|
signature[64] += 27 // Transform V from 0/1 to 27/28 according to the yellow paper
|
||||||
|
|
@ -509,7 +498,7 @@ func signHash(data []byte) ([]byte, string) {
|
||||||
|
|
||||||
// Export returns encrypted private key associated with the given address in web3 keystore format.
|
// Export returns encrypted private key associated with the given address in web3 keystore format.
|
||||||
func (api *SignerAPI) Export(ctx context.Context, addr common.Address) (json.RawMessage, error) {
|
func (api *SignerAPI) Export(ctx context.Context, addr common.Address) (json.RawMessage, error) {
|
||||||
res, err := api.ui.ApproveExport(&ExportRequest{Address: addr, Meta: MetadataFromContext(ctx)})
|
res, err := api.UI.ApproveExport(&ExportRequest{Address: addr, Meta: MetadataFromContext(ctx)})
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
@ -537,7 +526,7 @@ func (api *SignerAPI) Import(ctx context.Context, keyJSON json.RawMessage) (Acco
|
||||||
if len(be) == 0 {
|
if len(be) == 0 {
|
||||||
return Account{}, errors.New("password based accounts not supported")
|
return Account{}, errors.New("password based accounts not supported")
|
||||||
}
|
}
|
||||||
res, err := api.ui.ApproveImport(&ImportRequest{Meta: MetadataFromContext(ctx)})
|
res, err := api.UI.ApproveImport(&ImportRequest{Meta: MetadataFromContext(ctx)})
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return Account{}, err
|
return Account{}, err
|
||||||
|
|
@ -547,7 +536,7 @@ func (api *SignerAPI) Import(ctx context.Context, keyJSON json.RawMessage) (Acco
|
||||||
}
|
}
|
||||||
acc, err := be[0].(*keystore.KeyStore).Import(keyJSON, res.OldPassword, res.NewPassword)
|
acc, err := be[0].(*keystore.KeyStore).Import(keyJSON, res.OldPassword, res.NewPassword)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
api.ui.ShowError(err.Error())
|
api.UI.ShowError(err.Error())
|
||||||
return Account{}, err
|
return Account{}, err
|
||||||
}
|
}
|
||||||
return Account{Typ: "Account", URL: acc.URL, Address: acc.Address}, nil
|
return Account{Typ: "Account", URL: acc.URL, Address: acc.Address}, nil
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package signer
|
package core
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
|
@ -35,9 +35,9 @@ func (ui *HeadlessUI) ApproveTx(request *SignTxRequest) (SignTxResponse, error)
|
||||||
case "Y":
|
case "Y":
|
||||||
return SignTxResponse{request.Transaction, true, <-ui.controller}, nil
|
return SignTxResponse{request.Transaction, true, <-ui.controller}, nil
|
||||||
case "M": //Modify
|
case "M": //Modify
|
||||||
old := (*big.Int)(request.Transaction.Value)
|
old := big.Int(request.Transaction.Value)
|
||||||
newVal := big.NewInt(0).Add(old, big.NewInt(1))
|
newVal := big.NewInt(0).Add(&old, big.NewInt(1))
|
||||||
request.Transaction.Value = (*hexutil.Big)(newVal)
|
request.Transaction.Value = hexutil.Big(*newVal)
|
||||||
return SignTxResponse{request.Transaction, true, <-ui.controller}, nil
|
return SignTxResponse{request.Transaction, true, <-ui.controller}, nil
|
||||||
default:
|
default:
|
||||||
return SignTxResponse{request.Transaction, false, ""}, nil
|
return SignTxResponse{request.Transaction, false, ""}, nil
|
||||||
|
|
@ -106,7 +106,7 @@ func setup(t *testing.T) (*SignerAPI, chan string) {
|
||||||
|
|
||||||
controller := make(chan string, 10)
|
controller := make(chan string, 10)
|
||||||
|
|
||||||
db, err := NewAbiDBFromFile(fmt.Sprintf("./4byte.json"))
|
db, err := NewAbiDBFromFile(fmt.Sprintf("../4byte.json"))
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.Fatalf(err.Error())
|
utils.Fatalf(err.Error())
|
||||||
|
|
@ -238,9 +238,9 @@ func TestSignData(t *testing.T) {
|
||||||
}
|
}
|
||||||
func mkTestTx(from common.MixedcaseAddress) SendTxArgs {
|
func mkTestTx(from common.MixedcaseAddress) SendTxArgs {
|
||||||
to := common.NewMixedcaseAddress(common.HexToAddress("0x1337"))
|
to := common.NewMixedcaseAddress(common.HexToAddress("0x1337"))
|
||||||
gas := (*hexutil.Big)(big.NewInt(21000))
|
gas := (hexutil.Big)(*big.NewInt(21000))
|
||||||
gasPrice := (*hexutil.Big)(big.NewInt(2000000000))
|
gasPrice := (hexutil.Big)(*big.NewInt(2000000000))
|
||||||
value := (*hexutil.Big)(big.NewInt(1e18))
|
value := (hexutil.Big)(*big.NewInt(1e18))
|
||||||
nonce := (hexutil.Uint64)(0)
|
nonce := (hexutil.Uint64)(0)
|
||||||
data := hexutil.Bytes(common.Hex2Bytes("01020304050607080a"))
|
data := hexutil.Bytes(common.Hex2Bytes("01020304050607080a"))
|
||||||
tx := SendTxArgs{
|
tx := SendTxArgs{
|
||||||
|
|
@ -250,7 +250,7 @@ func mkTestTx(from common.MixedcaseAddress) SendTxArgs {
|
||||||
GasPrice: gasPrice,
|
GasPrice: gasPrice,
|
||||||
Value: value,
|
Value: value,
|
||||||
Data: &data,
|
Data: &data,
|
||||||
Nonce: &nonce}
|
Nonce: nonce}
|
||||||
return tx
|
return tx
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -14,7 +14,7 @@
|
||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
|
// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
package signer
|
package core
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
@ -13,7 +13,7 @@
|
||||||
//
|
//
|
||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
|
// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||||
package signer
|
package core
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
|
|
@ -181,7 +181,7 @@ func (ui *CommandlineUI) ApproveImport(request *ImportRequest) (ImportResponse,
|
||||||
}
|
}
|
||||||
|
|
||||||
// ApproveListing prompt the user for confirmation to list accounts
|
// ApproveListing prompt the user for confirmation to list accounts
|
||||||
// the list of accounts to list can be modified by the ui
|
// the list of accounts to list can be modified by the UI
|
||||||
func (ui *CommandlineUI) ApproveListing(request *ListRequest) (ListResponse, error) {
|
func (ui *CommandlineUI) ApproveListing(request *ListRequest) (ListResponse, error) {
|
||||||
|
|
||||||
ui.mu.Lock()
|
ui.mu.Lock()
|
||||||
|
|
@ -15,7 +15,7 @@
|
||||||
// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
|
// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||||
//
|
//
|
||||||
|
|
||||||
package signer
|
package core
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
@ -14,7 +14,7 @@
|
||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
|
// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
package signer
|
package core
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
|
@ -66,10 +66,10 @@ type TransactionArg struct {
|
||||||
type SendTxArgs struct {
|
type SendTxArgs struct {
|
||||||
From common.MixedcaseAddress `json:"from"`
|
From common.MixedcaseAddress `json:"from"`
|
||||||
To *common.MixedcaseAddress `json:"to"`
|
To *common.MixedcaseAddress `json:"to"`
|
||||||
Gas *hexutil.Big `json:"gas"`
|
Gas hexutil.Big `json:"gas"`
|
||||||
GasPrice *hexutil.Big `json:"gasPrice"`
|
GasPrice hexutil.Big `json:"gasPrice"`
|
||||||
Value *hexutil.Big `json:"value"`
|
Value hexutil.Big `json:"value"`
|
||||||
Nonce *hexutil.Uint64 `json:"nonce"`
|
Nonce hexutil.Uint64 `json:"nonce"`
|
||||||
// We accept "data" and "input" for backwards-compatibility reasons.
|
// We accept "data" and "input" for backwards-compatibility reasons.
|
||||||
Data *hexutil.Bytes `json:"data"`
|
Data *hexutil.Bytes `json:"data"`
|
||||||
Input *hexutil.Bytes `json:"input"`
|
Input *hexutil.Bytes `json:"input"`
|
||||||
|
|
@ -91,7 +91,7 @@ func (args *SendTxArgs) toTransaction() *types.Transaction {
|
||||||
input = *args.Input
|
input = *args.Input
|
||||||
}
|
}
|
||||||
if args.To == nil {
|
if args.To == nil {
|
||||||
return types.NewContractCreation(uint64(*args.Nonce), (*big.Int)(args.Value), (*big.Int)(args.Gas), (*big.Int)(args.GasPrice), input)
|
return types.NewContractCreation(uint64(args.Nonce), (*big.Int)(&args.Value), (*big.Int)(&args.Gas), (*big.Int)(&args.GasPrice), input)
|
||||||
}
|
}
|
||||||
return types.NewTransaction(uint64(*args.Nonce), (*args.To).Address(), (*big.Int)(args.Value), (*big.Int)(args.Gas), (*big.Int)(args.GasPrice), input)
|
return types.NewTransaction(uint64(args.Nonce), args.To.Address(), (*big.Int)(&args.Value), (*big.Int)(&args.Gas), (*big.Int)(&args.GasPrice), input)
|
||||||
}
|
}
|
||||||
|
|
@ -16,7 +16,7 @@
|
||||||
|
|
||||||
// signer is a utility that can be used so sign transactions and
|
// signer is a utility that can be used so sign transactions and
|
||||||
// arbitrary data.
|
// arbitrary data.
|
||||||
package signer
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
@ -33,6 +33,7 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/node"
|
"github.com/ethereum/go-ethereum/node"
|
||||||
"github.com/ethereum/go-ethereum/rpc"
|
"github.com/ethereum/go-ethereum/rpc"
|
||||||
"gopkg.in/urfave/cli.v1"
|
"gopkg.in/urfave/cli.v1"
|
||||||
|
"github.com/ethereum/go-ethereum/cmd/signer/core"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
|
@ -90,7 +91,7 @@ func main() {
|
||||||
app.Action = func(c *cli.Context) error {
|
app.Action = func(c *cli.Context) error {
|
||||||
|
|
||||||
var (
|
var (
|
||||||
ui SignerUI
|
ui core.SignerUI
|
||||||
)
|
)
|
||||||
// Set up the logger to print everything
|
// Set up the logger to print everything
|
||||||
logOutput := os.Stdout
|
logOutput := os.Stdout
|
||||||
|
|
@ -100,14 +101,14 @@ func main() {
|
||||||
log.Root().SetHandler(log.LvlFilterHandler(log.Lvl(c.Int("loglevel")), log.StreamHandler(logOutput, log.TerminalFormat(true))))
|
log.Root().SetHandler(log.LvlFilterHandler(log.Lvl(c.Int("loglevel")), log.StreamHandler(logOutput, log.TerminalFormat(true))))
|
||||||
|
|
||||||
if c.Bool("stdio-ui") {
|
if c.Bool("stdio-ui") {
|
||||||
ui = NewStdIOUI()
|
ui = core.NewStdIOUI()
|
||||||
} else {
|
} else {
|
||||||
ui = NewCommandlineUI()
|
ui = core.NewCommandlineUI()
|
||||||
}
|
}
|
||||||
if c.Bool("stdio-ui") {
|
if c.Bool("stdio-ui") {
|
||||||
log.Info("Using stdin/stdout as UI-channel")
|
log.Info("Using stdin/stdout as UI-channel")
|
||||||
}
|
}
|
||||||
db, err := NewAbiDBFromFile(c.String("4bytedb"))
|
db, err := core.NewAbiDBFromFile(c.String("4bytedb"))
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.Fatalf(err.Error())
|
utils.Fatalf(err.Error())
|
||||||
|
|
@ -115,12 +116,12 @@ func main() {
|
||||||
log.Info("Loaded 4byte db", "signatures", db.Size(), "file", c.String("4bytedb"))
|
log.Info("Loaded 4byte db", "signatures", db.Size(), "file", c.String("4bytedb"))
|
||||||
|
|
||||||
var (
|
var (
|
||||||
api ExternalAPI
|
api core.ExternalAPI
|
||||||
listener net.Listener
|
listener net.Listener
|
||||||
server = rpc.NewServer()
|
server = rpc.NewServer()
|
||||||
)
|
)
|
||||||
|
|
||||||
api_impl := NewSignerAPI(
|
api_impl := core.NewSignerAPI(
|
||||||
c.Int64(utils.NetworkIdFlag.Name),
|
c.Int64(utils.NetworkIdFlag.Name),
|
||||||
c.String("keystore"),
|
c.String("keystore"),
|
||||||
c.Bool(utils.NoUSBFlag.Name),
|
c.Bool(utils.NoUSBFlag.Name),
|
||||||
|
|
@ -131,7 +132,7 @@ func main() {
|
||||||
|
|
||||||
// Audit logging
|
// Audit logging
|
||||||
if logfile := c.String("auditlog"); logfile != "" {
|
if logfile := c.String("auditlog"); logfile != "" {
|
||||||
api, err = NewAuditLogger(logfile, api_impl)
|
api, err = core.NewAuditLogger(logfile, api_impl)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.Fatalf(err.Error())
|
utils.Fatalf(err.Error())
|
||||||
}
|
}
|
||||||
|
|
@ -170,7 +171,7 @@ func main() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func testExternalUI(api *SignerAPI) {
|
func testExternalUI(api *core.SignerAPI) {
|
||||||
|
|
||||||
ctx := context.WithValue(context.Background(), "remote", "signer binary")
|
ctx := context.WithValue(context.Background(), "remote", "signer binary")
|
||||||
ctx = context.WithValue(ctx, "scheme", "in-proc")
|
ctx = context.WithValue(ctx, "scheme", "in-proc")
|
||||||
|
|
@ -178,17 +179,17 @@ func testExternalUI(api *SignerAPI) {
|
||||||
|
|
||||||
errs := make([]string, 0)
|
errs := make([]string, 0)
|
||||||
|
|
||||||
api.ui.ShowInfo("Testing 'ShowInfo'")
|
api.UI.ShowInfo("Testing 'ShowInfo'")
|
||||||
api.ui.ShowError("Testing 'ShowError'")
|
api.UI.ShowError("Testing 'ShowError'")
|
||||||
|
|
||||||
checkErr := func(method string, err error) {
|
checkErr := func(method string, err error) {
|
||||||
if err != nil && err != ErrRequestDenied {
|
if err != nil && err != core.ErrRequestDenied {
|
||||||
errs = append(errs, fmt.Sprintf("%v: %v", method, err.Error()))
|
errs = append(errs, fmt.Sprintf("%v: %v", method, err.Error()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
_, err = api.SignTransaction(ctx, SendTxArgs{From:common.MixedcaseAddress{}}, nil)
|
_, err = api.SignTransaction(ctx, core.SendTxArgs{From:common.MixedcaseAddress{}}, nil)
|
||||||
checkErr("SignTransaction", err)
|
checkErr("SignTransaction", err)
|
||||||
_, err = api.Sign(ctx, common.MixedcaseAddress{}, common.Hex2Bytes("01020304"))
|
_, err = api.Sign(ctx, common.MixedcaseAddress{}, common.Hex2Bytes("01020304"))
|
||||||
checkErr("Sign", err)
|
checkErr("Sign", err)
|
||||||
|
|
@ -201,7 +202,7 @@ func testExternalUI(api *SignerAPI) {
|
||||||
_, err = api.Import(ctx, json.RawMessage{})
|
_, err = api.Import(ctx, json.RawMessage{})
|
||||||
checkErr("Import", err)
|
checkErr("Import", err)
|
||||||
|
|
||||||
api.ui.ShowInfo("Tests completed")
|
api.UI.ShowInfo("Tests completed")
|
||||||
|
|
||||||
if len(errs) > 0 {
|
if len(errs) > 0 {
|
||||||
log.Error("Got errors")
|
log.Error("Got errors")
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,6 @@ package rules
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/ethereum/go-ethereum/cmd/signer"
|
|
||||||
"github.com/ethereum/go-ethereum/cmd/signer/rules/deps"
|
"github.com/ethereum/go-ethereum/cmd/signer/rules/deps"
|
||||||
"github.com/ethereum/go-ethereum/cmd/signer/storage"
|
"github.com/ethereum/go-ethereum/cmd/signer/storage"
|
||||||
"github.com/ethereum/go-ethereum/internal/ethapi"
|
"github.com/ethereum/go-ethereum/internal/ethapi"
|
||||||
|
|
@ -27,6 +26,7 @@ import (
|
||||||
"github.com/robertkrimen/otto"
|
"github.com/robertkrimen/otto"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
"github.com/ethereum/go-ethereum/cmd/signer/core"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|
@ -48,7 +48,7 @@ func consoleOutput(call otto.FunctionCall) otto.Value {
|
||||||
// file for each defined UI-method
|
// file for each defined UI-method
|
||||||
type rulesetUi struct {
|
type rulesetUi struct {
|
||||||
vm *otto.Otto // The JS vm
|
vm *otto.Otto // The JS vm
|
||||||
next signer.SignerUI // The next handler, for manual processing
|
next core.SignerUI // The next handler, for manual processing
|
||||||
storage storage.Storage
|
storage storage.Storage
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -104,45 +104,45 @@ func (r *rulesetUi) checkApproval(jsfunc string, jsarg []byte, err error) error
|
||||||
return fmt.Errorf("rejected")
|
return fmt.Errorf("rejected")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *rulesetUi) ApproveTx(request *signer.SignTxRequest) (signer.SignTxResponse, error) {
|
func (r *rulesetUi) ApproveTx(request *core.SignTxRequest) (core.SignTxResponse, error) {
|
||||||
jsonreq, err := json.Marshal(request)
|
jsonreq, err := json.Marshal(request)
|
||||||
if err = r.checkApproval("ApproveTx", jsonreq, err); err == nil {
|
if err = r.checkApproval("ApproveTx", jsonreq, err); err == nil {
|
||||||
return signer.SignTxResponse{Transaction: request.Transaction, Approved: true, Password: ""}, nil
|
return core.SignTxResponse{Transaction: request.Transaction, Approved: true, Password: ""}, nil
|
||||||
}
|
}
|
||||||
return signer.SignTxResponse{Approved: false}, err
|
return core.SignTxResponse{Approved: false}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *rulesetUi) ApproveSignData(request *signer.SignDataRequest) (signer.SignDataResponse, error) {
|
func (r *rulesetUi) ApproveSignData(request *core.SignDataRequest) (core.SignDataResponse, error) {
|
||||||
jsonreq, err := json.Marshal(request)
|
jsonreq, err := json.Marshal(request)
|
||||||
if err = r.checkApproval("ApproveTx", jsonreq, err); err == nil {
|
if err = r.checkApproval("ApproveTx", jsonreq, err); err == nil {
|
||||||
return signer.SignDataResponse{Approved: true, Password: ""}, nil
|
return core.SignDataResponse{Approved: true, Password: ""}, nil
|
||||||
}
|
}
|
||||||
return signer.SignDataResponse{Approved: false, Password: ""}, err
|
return core.SignDataResponse{Approved: false, Password: ""}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *rulesetUi) ApproveExport(request *signer.ExportRequest) (signer.ExportResponse, error) {
|
func (r *rulesetUi) ApproveExport(request *core.ExportRequest) (core.ExportResponse, error) {
|
||||||
jsonreq, err := json.Marshal(request)
|
jsonreq, err := json.Marshal(request)
|
||||||
if err = r.checkApproval("ApproveTx", jsonreq, err); err == nil {
|
if err = r.checkApproval("ApproveTx", jsonreq, err); err == nil {
|
||||||
return signer.ExportResponse{Approved: true}, nil
|
return core.ExportResponse{Approved: true}, nil
|
||||||
}
|
}
|
||||||
return signer.ExportResponse{Approved: false}, err
|
return core.ExportResponse{Approved: false}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *rulesetUi) ApproveImport(request *signer.ImportRequest) (signer.ImportResponse, error) {
|
func (r *rulesetUi) ApproveImport(request *core.ImportRequest) (core.ImportResponse, error) {
|
||||||
// This cannot be handled by rules, requires setting a password
|
// This cannot be handled by rules, requires setting a password
|
||||||
// dispatch to next
|
// dispatch to next
|
||||||
return r.next.ApproveImport(request)
|
return r.next.ApproveImport(request)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *rulesetUi) ApproveListing(request *signer.ListRequest) (signer.ListResponse, error) {
|
func (r *rulesetUi) ApproveListing(request *core.ListRequest) (core.ListResponse, error) {
|
||||||
jsonreq, err := json.Marshal(request)
|
jsonreq, err := json.Marshal(request)
|
||||||
if err = r.checkApproval("ApproveListing", jsonreq, err); err == nil {
|
if err = r.checkApproval("ApproveListing", jsonreq, err); err == nil {
|
||||||
return signer.ListResponse{Accounts: request.Accounts}, nil
|
return core.ListResponse{Accounts: request.Accounts}, nil
|
||||||
}
|
}
|
||||||
return signer.ListResponse{}, err
|
return core.ListResponse{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *rulesetUi) ApproveNewAccount(request *signer.NewAccountRequest) (signer.NewAccountResponse, error) {
|
func (r *rulesetUi) ApproveNewAccount(request *core.NewAccountRequest) (core.NewAccountResponse, error) {
|
||||||
// This cannot be handled by rules, requires setting a password
|
// This cannot be handled by rules, requires setting a password
|
||||||
// dispatch to next
|
// dispatch to next
|
||||||
return r.next.ApproveNewAccount(request)
|
return r.next.ApproveNewAccount(request)
|
||||||
|
|
|
||||||
|
|
@ -3,13 +3,13 @@ package rules
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/ethereum/go-ethereum/accounts"
|
"github.com/ethereum/go-ethereum/accounts"
|
||||||
"github.com/ethereum/go-ethereum/cmd/signer"
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/internal/ethapi"
|
"github.com/ethereum/go-ethereum/internal/ethapi"
|
||||||
"math/big"
|
"math/big"
|
||||||
"testing"
|
"testing"
|
||||||
|
"github.com/ethereum/go-ethereum/cmd/signer/core"
|
||||||
)
|
)
|
||||||
|
|
||||||
const JS = `
|
const JS = `
|
||||||
|
|
@ -66,11 +66,11 @@ func initRuleEngine(js string) (*rulesetUi, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestListRequest(t *testing.T) {
|
func TestListRequest(t *testing.T) {
|
||||||
accs := make([]signer.Account, 5)
|
accs := make([]core.Account, 5)
|
||||||
|
|
||||||
for i, _ := range accs {
|
for i, _ := range accs {
|
||||||
addr := fmt.Sprintf("000000000000000000000000000000000000000%x", i)
|
addr := fmt.Sprintf("000000000000000000000000000000000000000%x", i)
|
||||||
acc := signer.Account{
|
acc := core.Account{
|
||||||
Address: common.BytesToAddress(common.Hex2Bytes(addr)),
|
Address: common.BytesToAddress(common.Hex2Bytes(addr)),
|
||||||
URL: accounts.URL{Scheme: "test", Path: fmt.Sprintf("acc-%d", i)},
|
URL: accounts.URL{Scheme: "test", Path: fmt.Sprintf("acc-%d", i)},
|
||||||
}
|
}
|
||||||
|
|
@ -84,9 +84,9 @@ func TestListRequest(t *testing.T) {
|
||||||
t.Errorf("Couldn't create evaluator %v", err)
|
t.Errorf("Couldn't create evaluator %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
resp, err := r.ApproveListing(&signer.ListRequest{
|
resp, err := r.ApproveListing(&core.ListRequest{
|
||||||
accs,
|
accs,
|
||||||
signer.Metadata{
|
core.Metadata{
|
||||||
"remoteip", "localip", "inproc",
|
"remoteip", "localip", "inproc",
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
@ -126,12 +126,12 @@ func TestSignTxRequest(t *testing.T) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
fmt.Printf("to %v", to.Address().String())
|
fmt.Printf("to %v", to.Address().String())
|
||||||
resp, err := r.ApproveTx(&signer.SignTxRequest{
|
resp, err := r.ApproveTx(&core.SignTxRequest{
|
||||||
Transaction: signer.SendTxArgs{
|
Transaction: core.SendTxArgs{
|
||||||
From: *from,
|
From: *from,
|
||||||
To: to},
|
To: to},
|
||||||
Callinfo: "",
|
Callinfo: "",
|
||||||
Meta: signer.Metadata{"remoteip", "localip", "inproc"},
|
Meta: core.Metadata{"remoteip", "localip", "inproc"},
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("Unexpected error %v", err)
|
t.Errorf("Unexpected error %v", err)
|
||||||
|
|
@ -290,7 +290,7 @@ const ExampleTxWindow = `
|
||||||
|
|
||||||
`
|
`
|
||||||
|
|
||||||
func dummyTx(value *hexutil.Big) *signer.SignTxRequest {
|
func dummyTx(value hexutil.Big) *core.SignTxRequest {
|
||||||
|
|
||||||
to, _ := mixAddr("000000000000000000000000000000000000dead")
|
to, _ := mixAddr("000000000000000000000000000000000000dead")
|
||||||
from, _ := mixAddr("000000000000000000000000000000000000dead")
|
from, _ := mixAddr("000000000000000000000000000000000000dead")
|
||||||
|
|
@ -298,17 +298,17 @@ func dummyTx(value *hexutil.Big) *signer.SignTxRequest {
|
||||||
gas := hexutil.Big(*big.NewInt(21000))
|
gas := hexutil.Big(*big.NewInt(21000))
|
||||||
gasPrice := hexutil.Big(*big.NewInt(2000000))
|
gasPrice := hexutil.Big(*big.NewInt(2000000))
|
||||||
|
|
||||||
return &signer.SignTxRequest{
|
return &core.SignTxRequest{
|
||||||
Transaction: signer.SendTxArgs{
|
Transaction: core.SendTxArgs{
|
||||||
From: *from,
|
From: *from,
|
||||||
To: to,
|
To: to,
|
||||||
Value: value,
|
Value: value,
|
||||||
Nonce: &n,
|
Nonce: n,
|
||||||
GasPrice: &gas,
|
GasPrice: gas,
|
||||||
Gas: &gasPrice,
|
Gas: gasPrice,
|
||||||
},
|
},
|
||||||
Callinfo: "Warning, all your base are bellong to us",
|
Callinfo: "Warning, all your base are bellong to us",
|
||||||
Meta: signer.Metadata{"remoteip", "localip", "inproc"},
|
Meta: core.Metadata{"remoteip", "localip", "inproc"},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
func dummySigned(value *big.Int) *types.Transaction {
|
func dummySigned(value *big.Int) *types.Transaction {
|
||||||
|
|
@ -335,7 +335,7 @@ func TestLimitWindow(t *testing.T) {
|
||||||
h := hexutil.Big(*v)
|
h := hexutil.Big(*v)
|
||||||
// The first three should succeed
|
// The first three should succeed
|
||||||
for i := 0; i < 3; i++ {
|
for i := 0; i < 3; i++ {
|
||||||
unsigned := dummyTx(&h)
|
unsigned := dummyTx(h)
|
||||||
resp, err := r.ApproveTx(unsigned)
|
resp, err := r.ApproveTx(unsigned)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("Unexpected error %v", err)
|
t.Errorf("Unexpected error %v", err)
|
||||||
|
|
@ -352,7 +352,7 @@ func TestLimitWindow(t *testing.T) {
|
||||||
r.OnApprovedTx(response)
|
r.OnApprovedTx(response)
|
||||||
}
|
}
|
||||||
// Fourth should fail
|
// Fourth should fail
|
||||||
resp, err := r.ApproveTx(dummyTx(&h))
|
resp, err := r.ApproveTx(dummyTx(h))
|
||||||
if resp.Approved {
|
if resp.Approved {
|
||||||
t.Errorf("Expected check to resolve to 'Reject'")
|
t.Errorf("Expected check to resolve to 'Reject'")
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue