mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-16 00:43:46 +00:00
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}
This commit is contained in:
parent
ad0a31f9a4
commit
4ba89772ac
3 changed files with 43 additions and 72 deletions
|
|
@ -57,7 +57,7 @@ var PrecompiledContractsMetropolis = map[common.Address]PrecompiledContract{
|
||||||
common.BytesToAddress([]byte{4}): &dataCopy{},
|
common.BytesToAddress([]byte{4}): &dataCopy{},
|
||||||
common.BytesToAddress([]byte{5}): &bigModexp{},
|
common.BytesToAddress([]byte{5}): &bigModexp{},
|
||||||
common.BytesToAddress([]byte{6}): &bn256Add{},
|
common.BytesToAddress([]byte{6}): &bn256Add{},
|
||||||
common.BytesToAddress([]byte{6}): &bn256ScalarMul{},
|
common.BytesToAddress([]byte{7}): &bn256ScalarMul{},
|
||||||
common.BytesToAddress([]byte{8}): &pairing{},
|
common.BytesToAddress([]byte{8}): &pairing{},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -206,7 +206,7 @@ func (c *bigModexp) Run(input []byte) ([]byte, error) {
|
||||||
}
|
}
|
||||||
mod := new(big.Int).SetBytes(input[:modLen])
|
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{}
|
type bn256Add struct{}
|
||||||
|
|
@ -220,37 +220,7 @@ func (c *bn256Add) RequiredGas(input []byte) uint64 {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *bn256Add) Run(in []byte) ([]byte, error) {
|
func (c *bn256Add) Run(in []byte) ([]byte, error) {
|
||||||
if len(in) != 96 {
|
in = common.RightPadBytes(in, 128)
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
||||||
x, onCurve := new(bn256.G1).Unmarshal(in[:64])
|
x, onCurve := new(bn256.G1).Unmarshal(in[:64])
|
||||||
if !onCurve {
|
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 {
|
if gx.Cmp(bn256.P) >= 0 || gy.Cmp(bn256.P) >= 0 {
|
||||||
return nil, errInvalidCurvePoint
|
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
|
// pairing implements a pairing pre-compile for the bn256 curve
|
||||||
|
|
|
||||||
|
|
@ -104,8 +104,8 @@ type EVM struct {
|
||||||
abort int32
|
abort int32
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewEVM retutrns a new EVM evmironment. The returned EVM is not thread safe
|
// NewEVM retutrns a new EVM . The returned EVM is not thread safe and should
|
||||||
// and should only ever be used *once*.
|
// only ever be used *once*.
|
||||||
func NewEVM(ctx Context, statedb StateDB, chainConfig *params.ChainConfig, vmConfig Config) *EVM {
|
func NewEVM(ctx Context, statedb StateDB, chainConfig *params.ChainConfig, vmConfig Config) *EVM {
|
||||||
evm := &EVM{
|
evm := &EVM{
|
||||||
Context: ctx,
|
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
|
// 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.
|
// only.
|
||||||
contract := NewContract(caller, to, new(big.Int), gas)
|
contract := NewContract(caller, to, new(big.Int), gas)
|
||||||
contract.SetCallCode(&addr, evm.StateDB.GetCodeHash(addr), evm.StateDB.GetCode(addr))
|
contract.SetCallCode(&addr, evm.StateDB.GetCodeHash(addr), evm.StateDB.GetCode(addr))
|
||||||
|
|
|
||||||
|
|
@ -56,43 +56,12 @@ type operation struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
frontierInstructionSet = NewFrontierInstructionSet()
|
frontierInstructionSet = NewFrontierInstructionSet()
|
||||||
homesteadInstructionSet = NewHomesteadInstructionSet()
|
homesteadInstructionSet = NewHomesteadInstructionSet()
|
||||||
metropolisInstructionSet = NewMetropolisInstructionSet()
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func NewMetropolisInstructionSet() [256]operation {
|
// NewHomesteadInstructionSet returns the frontier and homestead
|
||||||
instructionSet := NewHomesteadInstructionSet()
|
// instructions that can be executed during the homestead phase.
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewHomesteadInstructionSet() [256]operation {
|
func NewHomesteadInstructionSet() [256]operation {
|
||||||
instructionSet := NewFrontierInstructionSet()
|
instructionSet := NewFrontierInstructionSet()
|
||||||
instructionSet[DELEGATECALL] = operation{
|
instructionSet[DELEGATECALL] = operation{
|
||||||
|
|
@ -841,6 +810,7 @@ func NewFrontierInstructionSet() [256]operation {
|
||||||
validateStack: makeStackFunc(2, 0),
|
validateStack: makeStackFunc(2, 0),
|
||||||
memorySize: memoryLog,
|
memorySize: memoryLog,
|
||||||
valid: true,
|
valid: true,
|
||||||
|
writes: true,
|
||||||
},
|
},
|
||||||
LOG1: {
|
LOG1: {
|
||||||
execute: makeLog(1),
|
execute: makeLog(1),
|
||||||
|
|
@ -848,6 +818,7 @@ func NewFrontierInstructionSet() [256]operation {
|
||||||
validateStack: makeStackFunc(3, 0),
|
validateStack: makeStackFunc(3, 0),
|
||||||
memorySize: memoryLog,
|
memorySize: memoryLog,
|
||||||
valid: true,
|
valid: true,
|
||||||
|
writes: true,
|
||||||
},
|
},
|
||||||
LOG2: {
|
LOG2: {
|
||||||
execute: makeLog(2),
|
execute: makeLog(2),
|
||||||
|
|
@ -855,6 +826,7 @@ func NewFrontierInstructionSet() [256]operation {
|
||||||
validateStack: makeStackFunc(4, 0),
|
validateStack: makeStackFunc(4, 0),
|
||||||
memorySize: memoryLog,
|
memorySize: memoryLog,
|
||||||
valid: true,
|
valid: true,
|
||||||
|
writes: true,
|
||||||
},
|
},
|
||||||
LOG3: {
|
LOG3: {
|
||||||
execute: makeLog(3),
|
execute: makeLog(3),
|
||||||
|
|
@ -862,6 +834,7 @@ func NewFrontierInstructionSet() [256]operation {
|
||||||
validateStack: makeStackFunc(5, 0),
|
validateStack: makeStackFunc(5, 0),
|
||||||
memorySize: memoryLog,
|
memorySize: memoryLog,
|
||||||
valid: true,
|
valid: true,
|
||||||
|
writes: true,
|
||||||
},
|
},
|
||||||
LOG4: {
|
LOG4: {
|
||||||
execute: makeLog(4),
|
execute: makeLog(4),
|
||||||
|
|
@ -869,6 +842,7 @@ func NewFrontierInstructionSet() [256]operation {
|
||||||
validateStack: makeStackFunc(6, 0),
|
validateStack: makeStackFunc(6, 0),
|
||||||
memorySize: memoryLog,
|
memorySize: memoryLog,
|
||||||
valid: true,
|
valid: true,
|
||||||
|
writes: true,
|
||||||
},
|
},
|
||||||
CREATE: {
|
CREATE: {
|
||||||
execute: opCreate,
|
execute: opCreate,
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue