From 4ba89772ac8843a6f69893b0a5e86ee06d34bad1 Mon Sep 17 00:00:00 2001 From: Jeffrey Wilcke Date: Sat, 3 Jun 2017 09:20:08 +0200 Subject: [PATCH] core/vm: review changes: mod-pad, contract addrs, bn256-arith, f&r * Right pad return data of native contract big mod exp to same length as the modulo input * Spelling * Make LOG{n} write operations so the throw during readonly * Right pad native contracts input with zeros * Fixed bn256{add, mul} --- core/vm/contracts.go | 65 +++++++++++++++++++++---------------------- core/vm/evm.go | 6 ++-- core/vm/jump_table.go | 44 ++++++----------------------- 3 files changed, 43 insertions(+), 72 deletions(-) diff --git a/core/vm/contracts.go b/core/vm/contracts.go index 084b99dadc..ea84877464 100644 --- a/core/vm/contracts.go +++ b/core/vm/contracts.go @@ -57,7 +57,7 @@ var PrecompiledContractsMetropolis = map[common.Address]PrecompiledContract{ common.BytesToAddress([]byte{4}): &dataCopy{}, common.BytesToAddress([]byte{5}): &bigModexp{}, common.BytesToAddress([]byte{6}): &bn256Add{}, - common.BytesToAddress([]byte{6}): &bn256ScalarMul{}, + common.BytesToAddress([]byte{7}): &bn256ScalarMul{}, common.BytesToAddress([]byte{8}): &pairing{}, } @@ -206,7 +206,7 @@ func (c *bigModexp) Run(input []byte) ([]byte, error) { } mod := new(big.Int).SetBytes(input[:modLen]) - return base.Exp(base, exp, mod).Bytes(), nil + return common.LeftPadBytes(base.Exp(base, exp, mod).Bytes(), len(input[:modLen])), nil } type bn256Add struct{} @@ -220,37 +220,7 @@ func (c *bn256Add) RequiredGas(input []byte) uint64 { } func (c *bn256Add) Run(in []byte) ([]byte, error) { - if len(in) != 96 { - return nil, errBadPrecompileInput - } - - g1, onCurve := new(bn256.G1).Unmarshal(in[:64]) - if !onCurve { - return nil, errNotOnCurve - } - x, y, _, _ := g1.CurvePoints() - if x.Cmp(bn256.P) >= 0 || y.Cmp(bn256.P) >= 0 { - return nil, errInvalidCurvePoint - } - g1.ScalarMult(g1, new(big.Int).SetBytes(in[64:])) - - return g1.Marshal(), nil -} - -type bn256ScalarMul struct{} - -// RequiredGas returns the gas required to execute the pre-compiled contract. -// -// This method does not require any overflow checking as the input size gas costs -// required for anything significant is so high it's impossible to pay for. -func (c *bn256ScalarMul) RequiredGas(input []byte) uint64 { - return 0 // TODO -} - -func (c *bn256ScalarMul) Run(in []byte) ([]byte, error) { - if len(in) != 128 { - return nil, errBadPrecompileInput - } + in = common.RightPadBytes(in, 128) x, onCurve := new(bn256.G1).Unmarshal(in[:64]) if !onCurve { @@ -269,8 +239,35 @@ func (c *bn256ScalarMul) Run(in []byte) ([]byte, error) { if gx.Cmp(bn256.P) >= 0 || gy.Cmp(bn256.P) >= 0 { return nil, errInvalidCurvePoint } + x.Add(x, y) - return x.Add(x, y).Marshal(), nil + return x.Marshal(), nil +} + +type bn256ScalarMul struct{} + +// RequiredGas returns the gas required to execute the pre-compiled contract. +// +// This method does not require any overflow checking as the input size gas costs +// required for anything significant is so high it's impossible to pay for. +func (c *bn256ScalarMul) RequiredGas(input []byte) uint64 { + return 0 // TODO +} + +func (c *bn256ScalarMul) Run(in []byte) ([]byte, error) { + in = common.RightPadBytes(in, 96) + + g1, onCurve := new(bn256.G1).Unmarshal(in[:64]) + if !onCurve { + return nil, errNotOnCurve + } + x, y, _, _ := g1.CurvePoints() + if x.Cmp(bn256.P) >= 0 || y.Cmp(bn256.P) >= 0 { + return nil, errInvalidCurvePoint + } + g1.ScalarMult(g1, new(big.Int).SetBytes(in[64:96])) + + return g1.Marshal(), nil } // pairing implements a pairing pre-compile for the bn256 curve diff --git a/core/vm/evm.go b/core/vm/evm.go index 8c8322bd16..37d502d264 100644 --- a/core/vm/evm.go +++ b/core/vm/evm.go @@ -104,8 +104,8 @@ type EVM struct { abort int32 } -// NewEVM retutrns a new EVM evmironment. The returned EVM is not thread safe -// and should only ever be used *once*. +// NewEVM retutrns a new EVM . The returned EVM is not thread safe and should +// only ever be used *once*. func NewEVM(ctx Context, statedb StateDB, chainConfig *params.ChainConfig, vmConfig Config) *EVM { evm := &EVM{ Context: ctx, @@ -153,7 +153,7 @@ func (evm *EVM) StaticCall(caller ContractRef, addr common.Address, input []byte } // initialise a new contract and set the code that is to be used by the - // E The contract is a scoped evmironment for this execution context + // EVM. The contract is a scoped evmironment for this execution context // only. contract := NewContract(caller, to, new(big.Int), gas) contract.SetCallCode(&addr, evm.StateDB.GetCodeHash(addr), evm.StateDB.GetCode(addr)) diff --git a/core/vm/jump_table.go b/core/vm/jump_table.go index 43d971dfb2..130532c5c8 100644 --- a/core/vm/jump_table.go +++ b/core/vm/jump_table.go @@ -56,43 +56,12 @@ type operation struct { } var ( - frontierInstructionSet = NewFrontierInstructionSet() - homesteadInstructionSet = NewHomesteadInstructionSet() - metropolisInstructionSet = NewMetropolisInstructionSet() + frontierInstructionSet = NewFrontierInstructionSet() + homesteadInstructionSet = NewHomesteadInstructionSet() ) -func NewMetropolisInstructionSet() [256]operation { - instructionSet := NewHomesteadInstructionSet() - instructionSet[STATIC_CALL] = operation{ - execute: opStaticCall, - gasCost: gasStaticCall, - validateStack: makeStackFunc(6, 1), - memorySize: memoryStaticCall, - valid: true, - } - instructionSet[REVERT] = operation{ - execute: opRevert, - gasCost: constGasFunc(GasFastestStep), - validateStack: makeStackFunc(2, 0), - valid: true, - reverts: true, - } - instructionSet[RETURNDATASIZE] = operation{ - execute: opReturnDataSize, - gasCost: constGasFunc(0), // TODO - validateStack: makeStackFunc(0, 1), - valid: true, - } - instructionSet[RETURNDATACOPY] = operation{ - execute: opReturnDataCopy, - gasCost: gasReturnDataCopy, - validateStack: makeStackFunc(3, 0), - memorySize: memoryReturnDataCopy, - valid: true, - } - return instructionSet -} - +// NewHomesteadInstructionSet returns the frontier and homestead +// instructions that can be executed during the homestead phase. func NewHomesteadInstructionSet() [256]operation { instructionSet := NewFrontierInstructionSet() instructionSet[DELEGATECALL] = operation{ @@ -841,6 +810,7 @@ func NewFrontierInstructionSet() [256]operation { validateStack: makeStackFunc(2, 0), memorySize: memoryLog, valid: true, + writes: true, }, LOG1: { execute: makeLog(1), @@ -848,6 +818,7 @@ func NewFrontierInstructionSet() [256]operation { validateStack: makeStackFunc(3, 0), memorySize: memoryLog, valid: true, + writes: true, }, LOG2: { execute: makeLog(2), @@ -855,6 +826,7 @@ func NewFrontierInstructionSet() [256]operation { validateStack: makeStackFunc(4, 0), memorySize: memoryLog, valid: true, + writes: true, }, LOG3: { execute: makeLog(3), @@ -862,6 +834,7 @@ func NewFrontierInstructionSet() [256]operation { validateStack: makeStackFunc(5, 0), memorySize: memoryLog, valid: true, + writes: true, }, LOG4: { execute: makeLog(4), @@ -869,6 +842,7 @@ func NewFrontierInstructionSet() [256]operation { validateStack: makeStackFunc(6, 0), memorySize: memoryLog, valid: true, + writes: true, }, CREATE: { execute: opCreate,