-
Notifications
You must be signed in to change notification settings - Fork 20.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
consensus, core/*: metropolis features #14337
Conversation
core/types/transaction_signing.go
Outdated
|
||
func isAbstractSigner(tx *Transaction) bool { | ||
v, r, s := tx.RawSignatureValues() | ||
return v.BitLen() == 0 && r.BitLen() == 0 && s.BitLen() == 0 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The EIP has changed and v
here needs to be the chain ID.
consensus/ethash/consensus.go
Outdated
x = big.NewInt(2) | ||
} | ||
z := new(big.Int).Sub(bigTime, bigParentTime) | ||
z.Div(x, big9) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't this be z.Div(z, big9)
?
core/vm/interpreter.go
Outdated
// may me left uninitialised and will be set the default | ||
// table. | ||
JumpTable [256]operation | ||
} | ||
|
||
// Interpreter is used to run Ethereum based contracts and will utilise the | ||
// passed environment to query external sources for state information. | ||
// passed evmironment to query external sources for state information. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's a fancy word.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
:-P screwed up find and replace
f5c98a4
to
8042bbe
Compare
core/state_processor.go
Outdated
// Create a new receipt for the transaction, storing the intermediate root and gas used by the tx | ||
// based on the eip phase, we're passing wether the root touch-delete accounts. | ||
receipt := types.NewReceipt(statedb.IntermediateRoot(config.IsEIP158(header.Number)).Bytes(), usedGas) | ||
receipt := types.NewReceipt(root, usedGas) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since the option 1 of EIP98 was chosen, so it's not enough to make Ah, no, this seems all fine.root
the empty sequence. The receipt has one less elements in Metropolis. See a log of a coredev meeting.
core/vm/contracts.go
Outdated
common.BytesToAddress([]byte{4}): &dataCopy{}, | ||
common.BytesToAddress([]byte{5}): &bigModexp{}, | ||
common.BytesToAddress([]byte{6}): &bn256Add{}, | ||
common.BytesToAddress([]byte{6}): &bn256ScalarMul{}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Address 6 is used twice, it seems.
core/vm/contracts.go
Outdated
} | ||
mod := new(big.Int).SetBytes(input[:modLen]) | ||
|
||
return base.Exp(base, exp, mod).Bytes(), nil |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The length of the result needs to be the same as that of mod
. See https://github.com/ethereum/EIPs/pull/198/files#diff-b02d15001884061861b0e92a735e7cefR11
core/vm/evm.go
Outdated
@@ -79,25 +104,72 @@ type EVM struct { | |||
abort int32 | |||
} | |||
|
|||
// NewEVM retutrns a new EVM evmironment. | |||
// NewEVM retutrns a new EVM evmironment. The returned EVM is not thread safe |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Now my brain thinks evmironment
is a word.
core/vm/evm.go
Outdated
} | ||
|
||
// 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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess this E
is EVM
.
ret, err = evm.interpreter.Run(snapshot, contract, input) | ||
// When an error was returned by the EVM or when setting the creation code | ||
// above we revert to the snapshot and consume any gas remaining. Additionally | ||
// when we're in homestead this also counts for code storage gas errors. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess we never hit here during Homestead.
core/vm/interpreter.go
Outdated
// if the interpreter is operating in readonly mode, make sure no | ||
// state-modifying operation is performed. | ||
if operation.writes || | ||
((op == CALL || op == CALLCODE) && stack.Back(3).BitLen() > 0) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LOG0
, LOG1
, LOG2
, LOG3
, LOG4
should be banned here as well. Currently their .writes
value is false.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This has been resolved. These instructions now have .writes == true
.
core/vm/contracts.go
Outdated
} | ||
|
||
func (c *bn256Add) Run(in []byte) ([]byte, error) { | ||
if len(in) != 96 { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the input is too short, it should be padded. I think this changed at some point.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe when I wrote this it was still up for debate, including changing the semantics of CALLDATALOAD (i.e. that it should throw)
return 0 // TODO | ||
} | ||
|
||
func (c *bn256Add) Run(in []byte) ([]byte, error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The type says bn256Add
but this function calls ScalarMult
.
return 0 // TODO | ||
} | ||
|
||
func (c *bn256ScalarMul) Run(in []byte) ([]byte, error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The type says bn256ScalarMul
but this function performs addition.
core/vm/contracts.go
Outdated
} | ||
|
||
func (c *bn256ScalarMul) Run(in []byte) ([]byte, error) { | ||
if len(in) != 128 { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The input should be padded if it's too short.
@obscuren yes, I know. I've been just reading the interesting parts (which was a reasonable thing to do after doing YP). |
2cff572
to
046fc67
Compare
046fc67
to
eab5213
Compare
@pirapira I've addressed your comments. Thanks again. |
eab5213
to
f90b410
Compare
I was trying to run in on Hive, but build fails:
|
core/vm/instructions.go
Outdated
@@ -729,7 +729,7 @@ func opReturnDataCopy(pc *uint64, evm *EVM, contract *Contract, memory *Memory, | |||
cOff = stack.pop() | |||
l = stack.pop() | |||
) | |||
memory.Set(mOff.Uint64(), l.Uint64(), getData(memory.lastReturn, cOff, l)) | |||
memory.Set(mOff.Uint64(), l.Uint64(), getData(evm.interpreter.returnData, cOff, l)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should generate an error if the operation tries to read out of bounds, as agreed on the last core dev call.
core/vm/interpreter.go
Outdated
@@ -228,7 +234,7 @@ func (in *Interpreter) Run(snapshot int, contract *Contract, input []byte) (ret | |||
// if the operation returned a value make sure that is also set | |||
// the last return data. | |||
if res != nil { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure this is sufficient.
In the case of CALL
, the res
may be nil
for various reasons, e.g. the balance being to low:
if !evm.Context.CanTransfer(evm.StateDB, caller.Address(), value) {
return nil, gas, ErrInsufficientBalance
}
The way it's written, I don't think RETURNDATA
would be cleared. I believe the returndata should be cleared immediately when CALL
is invoked.
Further, I believe that also CREATE
should clear the RETURNDATA
. But I'm not 100% certain in this case. @pirapira what's your take ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it would be better with
if operations.clearsReturndata{
in.returnData = res
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
References: ethereum/EIPs#211 (comment)
To summarize: Any opcode that attempts to create a new call stack frame resets the buffer of the current stack frame right before it executes, even if that opcode fails.
Also, from the EIP itself -
https://github.com/ethereum/EIPs/blob/aeaffcca26fa688f5015da7ce059c886e90ef374/EIPS/returndatacopy.md:
As an optimization, it is possible to share the return data buffer across call frames because only one will be non-empty at any time.
// to the chain identifier and r and s being 0. | ||
func isAbstractSigner(tx *Transaction, chainId *big.Int) bool { | ||
v, r, s := tx.RawSignatureValues() | ||
return v.Cmp(chainId) == 0 && r.BitLen() == 0 && s.BitLen() == 0 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A requirement for it being an abstract-signer tx, is that gasprice = 0, nonce = 0, value = 0
. Is this checked anywhere?
core/vm/jump_table.go
Outdated
} | ||
instructionSet[RETURNDATASIZE] = operation{ | ||
execute: opReturnDataSize, | ||
gasCost: constGasFunc(0), // TODO |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
According to https://github.com/ethereum/EIPs/blob/aeaffcca26fa688f5015da7ce059c886e90ef374/EIPS/returndatacopy.md#specification:
Gas costs: 2 (same as CALLDATASIZE)
Or rather, GasQuickStep
.
core/vm/instructions.go
Outdated
cOff = stack.pop() | ||
l = stack.pop() | ||
) | ||
memory.Set(mOff.Uint64(), l.Uint64(), getData(evm.interpreter.returnData, cOff, l)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should raise error in case the requested data is out of bounds - getData
pads with zeroes, afaik.
core/vm/interpreter.go
Outdated
// if the interpreter is operating in readonly mode, make sure no | ||
// state-modifying operation is performed. | ||
if operation.writes || | ||
((op == CALL || op == CALLCODE) && stack.Back(3).BitLen() > 0) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think a comment would be in order here to shed some light on what magic is contained within stack.Back(3)
At https://github.com/obscuren/go-ethereum/blob/metropolis-finalisation/core/vm/evm.go#L195:
You need to check for Metro, and if so, use I think. I'm actually not 100%. |
Reimplemented RETURNDATA such that the returndata buffer is isolated inside the interpreter rather than the memory object.
* 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}
* Changed the gas for RETURNDATASIZE * Added comments for read only check * Fixed opReturnDataCopy
9ec99ce
to
43577cd
Compare
@obscuren there's also an error in (but maybe ignore the gas calculation, I'm not sure it's correct) |
Superseded by #14726 (which itself is superseded already). |
Todos:
Done: