-
Notifications
You must be signed in to change notification settings - Fork 166
getTransactionReceipt - dynamic status generation #634
Conversation
core/state_transition.go
Outdated
if err != nil { | ||
err = nil | ||
if vmerr != nil && IsValueTransferErr(vmerr) { | ||
return nil, nil, nil, false, InvalidTxError(vmerr) |
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 vmerr was a value transfer error, return immediately
// transaction receipt status will be set to TxSuccess
eth/api.go
Outdated
@@ -1197,6 +1215,10 @@ func (s *PublicTransactionPoolAPI) GetTransactionReceipt(txHash common.Hash) (ma | |||
fields["contractAddress"] = receipt.ContractAddress | |||
} | |||
|
|||
if receipt.Status != types.TxStatusUnknown { | |||
fields["status"] = receipt.Status |
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.
- https://wiki.parity.io/JSONRPC-eth-module#eth_gettransactionreceipt
- https://github.com/paritytech/parity/blob/28c731881f2da0ceca4752dbcc1a8f9ad041f988/ethcore/types/src/receipt.rs#L62-L108
Continuing from sorpaas's point 2/3, we need to be careful about changing established eth_
namespaced APIs. So either we'll have to check block number, too, or create a new API method. I'd be keen to use his suggestion of etc_
, or our geth_
namespace. (Which one is a question worth talking moar about).
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.
Actually, we're not compatible anyways right now - because we're not returning nil
- we're just skipping the status
field.
core/state_processor.go
Outdated
@@ -106,6 +109,70 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB) (ty | |||
return receipts, allLogs, totalUsedGas, err | |||
} | |||
|
|||
func (p *StateProcessor) ReplayTransaction(txHash common.Hash, statedb *state.StateDB) (*types.Receipt, 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.
I would probably rename this, since "replaying transactions" is taken... EIP155.
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.
Yes, something like trace or playback seems better. Any other ideas?
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 like PlayBack.
eth/api.go
Outdated
if replayTransactions && receipt.Status == types.TxStatusUnknown { | ||
// TODO(tzdybal) - get rid of this nasty casting | ||
proc := s.bc.Processor().(*core.StateProcessor) | ||
statedb, err := s.bc.StateAt(s.bc.GetBlock(txBlock).Root()) |
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 you may need to use the state from the parent block.
https://github.com/ethereumproject/go-ethereum/blob/master/core/blockchain.go#L1633
eth/api.go
Outdated
@@ -54,6 +54,9 @@ import ( | |||
|
|||
const defaultGas = uint64(90000) | |||
|
|||
// TODO(tzdybal) - make it configurable parameter | |||
const replayTransactions = true |
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.
w/r/t my later comment, is this intended in order to make the API eth_getTransactionReceipt
output configurable? Or?
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.
Yes I was thinking about making it an option. Because, when we add dynamic state fetching, we will have a complicated situation for "fast" clients. After querying transactions, client won't be typically fast, the extra state will require extra disk space. And generation of status by re-executing transactions is extra cost (and maybe someone doesn't need status field).
I like the design in general. |
core/state_transition.go
Outdated
} | ||
|
||
requiredGas = new(big.Int).Set(self.gasUsed()) | ||
|
||
self.refundGas() | ||
self.state.AddBalance(self.env.Coinbase(), new(big.Int).Mul(self.gasUsed(), self.gasPrice)) | ||
|
||
return ret, requiredGas, self.gasUsed(), err | ||
return ret, requiredGas, self.gasUsed(), vmerr != nil, err |
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.
Seems kinda weird to return requiredGas, when it's just
requiredGas = new(big.Int).Set(self.gasUsed())`...
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.
Cleaned up.
241acf0
to
2bf5b3f
Compare
eth/api.go
Outdated
// Status field was introduced in ETH with EIP-609. For compatibility, we won't return status for | ||
// blocks before the fork. | ||
fields["status"] = nil | ||
if receipt.Status != types.TxStatusUnknown && blockIndex >= 4370000 { |
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 we keep this, I think it should be configurable via the chain config... somehow.
Since this implementation is only in reference to a fork, but not actually a part of a fork, this is a strange case.
Otherwise, we just eliminate this condition and return status if available for all blocks regardless of chain or consensus schemes (since this deals only with the API, not protocol).
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 really don't like keeping this API method 100% compatible with ETH.
IMHO we should keep one method (no extra methods in different namespaces), and "break" the compatibility (we're giving more functionality than ETH, and we're not compatible anyways right now).
Most useful solution will give us cleanest code.
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 agree, there is no goal to make it 100% compatible but to add useful feature for users
1d22e1e
to
0e3f485
Compare
solution: return new wrapped error inline
21069fd
to
584776b
Compare
eth/api.go
Outdated
@@ -1187,6 +1187,13 @@ func (s *PublicTransactionPoolAPI) GetTransactionReceipt(txHash common.Hash) (ma | |||
if err != nil { | |||
return nil, err | |||
} | |||
|
|||
if err := core.WriteReceipts(s.chainDb, receipts); err != nil { | |||
glog.V(logger.Warn).Infof("cannot save updated receipts: %v", err) |
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.
Do you think Warn/Info
is an appropriate level/severity for this? Or even possibly critical failure/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.
LGTM.
like other QUANTITY fields, like blockNumber ,cumulativeGasUsed and etc, is it better to make type of the field "status" as hex String? As web3 and web3j are both expects hex String , please refer to https://github.com/ethereum/wiki/wiki/JavaScript-API#web3ethgettransactionreceipt `public static BigInteger decodeQuantity(String value) {
Quantity fields are expected as hex string. |
No description provided.