diff options
Diffstat (limited to 'internal/ethapi')
-rw-r--r-- | internal/ethapi/api.go | 35 | ||||
-rw-r--r-- | internal/ethapi/backend.go | 2 | ||||
-rw-r--r-- | internal/ethapi/tracer.go | 2 | ||||
-rw-r--r-- | internal/ethapi/tracer_test.go | 6 |
4 files changed, 32 insertions, 13 deletions
diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go index b84bba516..561e72b01 100644 --- a/internal/ethapi/api.go +++ b/internal/ethapi/api.go @@ -287,11 +287,19 @@ func signHash(data []byte) []byte { // Sign calculates an Ethereum ECDSA signature for: // keccack256("\x19Ethereum Signed Message:\n" + len(message) + message)) // +// Note, the produced signature conforms to the secp256k1 curve R, S and V values, +// where the V value will be 27 or 28 for legacy reasons. +// // The key used to calculate the signature is decrypted with the given password. // // https://github.com/ethereum/go-ethereum/wiki/Management-APIs#personal_sign func (s *PrivateAccountAPI) Sign(ctx context.Context, data hexutil.Bytes, addr common.Address, passwd string) (hexutil.Bytes, error) { - return s.b.AccountManager().SignWithPassphrase(addr, passwd, signHash(data)) + signature, err := s.b.AccountManager().SignWithPassphrase(addr, passwd, signHash(data)) + if err != nil { + return nil, err + } + signature[64] += 27 // SignWithPassphrase uses canonical secp256k1 signatures (v = 0 or 1), transform to yellow paper + return signature, nil } // EcRecover returns the address for the account that was used to create the signature. @@ -300,15 +308,19 @@ func (s *PrivateAccountAPI) Sign(ctx context.Context, data hexutil.Bytes, addr c // hash = keccak256("\x19Ethereum Signed Message:\n"${message length}${message}) // addr = ecrecover(hash, signature) // +// Note, the signature must conform to the secp256k1 curve R, S and V values, where +// the V value must be be 27 or 28 for legacy reasons. +// // https://github.com/ethereum/go-ethereum/wiki/Management-APIs#personal_ecRecover func (s *PrivateAccountAPI) EcRecover(ctx context.Context, data, sig hexutil.Bytes) (common.Address, error) { if len(sig) != 65 { return common.Address{}, fmt.Errorf("signature must be 65 bytes long") } - // see crypto.Ecrecover description - if sig[64] == 27 || sig[64] == 28 { - sig[64] -= 27 + if sig[64] != 27 && sig[64] != 28 { + return common.Address{}, fmt.Errorf("invalid Ethereum signature (V is not 27 or 28)") } + sig[64] -= 27 // Transform yellow paper signatures to canonical secp256k1 form + rpk, err := crypto.Ecrecover(signHash(data), sig) if err != nil { return common.Address{}, err @@ -964,7 +976,7 @@ func (s *PublicTransactionPoolAPI) GetTransactionReceipt(txHash common.Hash) (ma func (s *PublicTransactionPoolAPI) sign(addr common.Address, tx *types.Transaction) (*types.Transaction, error) { signer := types.MakeSigner(s.b.ChainConfig(), s.b.CurrentBlock().Number()) - signature, err := s.b.AccountManager().SignEthereum(addr, signer.Hash(tx).Bytes()) + signature, err := s.b.AccountManager().Sign(addr, signer.Hash(tx).Bytes()) if err != nil { return nil, err } @@ -1046,11 +1058,10 @@ func (s *PublicTransactionPoolAPI) SendTransaction(ctx context.Context, args Sen } tx := args.toTransaction() signer := types.MakeSigner(s.b.ChainConfig(), s.b.CurrentBlock().Number()) - signature, err := s.b.AccountManager().SignEthereum(args.From, signer.Hash(tx).Bytes()) + signature, err := s.b.AccountManager().Sign(args.From, signer.Hash(tx).Bytes()) if err != nil { return common.Hash{}, err } - return submitTransaction(ctx, s.b, tx, signature) } @@ -1084,11 +1095,19 @@ func (s *PublicTransactionPoolAPI) SendRawTransaction(ctx context.Context, encod // Sign calculates an ECDSA signature for: // keccack256("\x19Ethereum Signed Message:\n" + len(message) + message). // +// Note, the produced signature conforms to the secp256k1 curve R, S and V values, +// where the V value will be 27 or 28 for legacy reasons. +// // The account associated with addr must be unlocked. // // https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_sign func (s *PublicTransactionPoolAPI) Sign(addr common.Address, data hexutil.Bytes) (hexutil.Bytes, error) { - return s.b.AccountManager().SignEthereum(addr, signHash(data)) + signature, err := s.b.AccountManager().Sign(addr, signHash(data)) + if err == nil { + // Sign uses canonical secp256k1 signatures (v = 0 or 1), transform to yellow paper + signature[64] += 27 + } + return signature, err } // SignTransactionResult represents a RLP encoded signed transaction. diff --git a/internal/ethapi/backend.go b/internal/ethapi/backend.go index 36d7e754b..ebb14a5b5 100644 --- a/internal/ethapi/backend.go +++ b/internal/ethapi/backend.go @@ -51,7 +51,7 @@ type Backend interface { GetBlock(ctx context.Context, blockHash common.Hash) (*types.Block, error) GetReceipts(ctx context.Context, blockHash common.Hash) (types.Receipts, error) GetTd(blockHash common.Hash) *big.Int - GetVMEnv(ctx context.Context, msg core.Message, state State, header *types.Header) (*vm.Environment, func() error, error) + GetVMEnv(ctx context.Context, msg core.Message, state State, header *types.Header) (*vm.EVM, func() error, error) // TxPool API SendTx(ctx context.Context, signedTx *types.Transaction) error RemoveTx(txHash common.Hash) diff --git a/internal/ethapi/tracer.go b/internal/ethapi/tracer.go index 6d632376b..ef107fc42 100644 --- a/internal/ethapi/tracer.go +++ b/internal/ethapi/tracer.go @@ -278,7 +278,7 @@ func wrapError(context string, err error) error { } // CaptureState implements the Tracer interface to trace a single step of VM execution -func (jst *JavascriptTracer) CaptureState(env *vm.Environment, pc uint64, op vm.OpCode, gas, cost *big.Int, memory *vm.Memory, stack *vm.Stack, contract *vm.Contract, depth int, err error) error { +func (jst *JavascriptTracer) CaptureState(env *vm.EVM, pc uint64, op vm.OpCode, gas, cost *big.Int, memory *vm.Memory, stack *vm.Stack, contract *vm.Contract, depth int, err error) error { if jst.err == nil { jst.memory.memory = memory jst.stack.stack = stack diff --git a/internal/ethapi/tracer_test.go b/internal/ethapi/tracer_test.go index 29814d783..65a23f55e 100644 --- a/internal/ethapi/tracer_test.go +++ b/internal/ethapi/tracer_test.go @@ -43,12 +43,12 @@ func (account) SetCode(common.Hash, []byte) {} func (account) ForEachStorage(cb func(key, value common.Hash) bool) {} func runTrace(tracer *JavascriptTracer) (interface{}, error) { - env := vm.NewEnvironment(vm.Context{}, nil, params.TestChainConfig, vm.Config{Debug: true, Tracer: tracer}) + env := vm.NewEVM(vm.Context{}, nil, params.TestChainConfig, vm.Config{Debug: true, Tracer: tracer}) contract := vm.NewContract(account{}, account{}, big.NewInt(0), big.NewInt(10000)) contract.Code = []byte{byte(vm.PUSH1), 0x1, byte(vm.PUSH1), 0x1, 0x0} - _, err := env.EVM().Run(contract, []byte{}) + _, err := env.Interpreter().Run(contract, []byte{}) if err != nil { return nil, err } @@ -133,7 +133,7 @@ func TestHaltBetweenSteps(t *testing.T) { t.Fatal(err) } - env := vm.NewEnvironment(vm.Context{}, nil, params.TestChainConfig, vm.Config{Debug: true, Tracer: tracer}) + env := vm.NewEVM(vm.Context{}, nil, params.TestChainConfig, vm.Config{Debug: true, Tracer: tracer}) contract := vm.NewContract(&account{}, &account{}, big.NewInt(0), big.NewInt(0)) tracer.CaptureState(env, 0, 0, big.NewInt(0), big.NewInt(0), nil, nil, contract, 0, nil) |