Skip to content
This repository has been archived by the owner on Oct 4, 2019. It is now read-only.

getTransactionReceipt - dynamic status generation #634

Merged
merged 17 commits into from
Jul 19, 2018
Merged

Conversation

tzdybal
Copy link
Contributor

@tzdybal tzdybal commented Jun 15, 2018

No description provided.

if err != nil {
err = nil
if vmerr != nil && IsValueTransferErr(vmerr) {
return nil, nil, nil, false, InvalidTxError(vmerr)
Copy link
Contributor

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
Copy link
Contributor

@whilei whilei Jun 15, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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).

Copy link
Contributor Author

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.

@@ -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) {
Copy link
Contributor

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.

Copy link
Contributor Author

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?

Copy link
Contributor

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())
Copy link
Contributor

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
Copy link
Contributor

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?

Copy link
Contributor Author

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).

@whilei
Copy link
Contributor

whilei commented Jun 15, 2018

I like the design in general.

}

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
Copy link
Contributor

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())`...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cleaned up.

@tzdybal tzdybal force-pushed the feature/tx-status branch 2 times, most recently from 241acf0 to 2bf5b3f Compare July 11, 2018 23:37
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 {
Copy link
Contributor

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).

Copy link
Contributor Author

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.

Copy link
Contributor

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

@tzdybal tzdybal force-pushed the feature/tx-status branch 2 times, most recently from 1d22e1e to 0e3f485 Compare July 18, 2018 11:06
@tzdybal tzdybal changed the title [WIP] getTransactionReceipt - dynamic status generation getTransactionReceipt - dynamic status generation Jul 18, 2018
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)
Copy link
Contributor

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?

Copy link
Contributor

@whilei whilei left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM.

@tzdybal tzdybal merged commit b65d29e into master Jul 19, 2018
@eyfl
Copy link

eyfl commented Jul 25, 2018

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
and
https://github.com/web3j/web3j/blob/master/core/src/main/java/org/web3j/protocol/core/methods/response/TransactionReceipt.java and https://github.com/web3j/web3j/blob/master/utils/src/main/java/org/web3j/utils/Numeric.java

`public static BigInteger decodeQuantity(String value) {

    if (!isValidHexQuantity(value)) {
       throw new MessageDecodingException("Value must be in format 0x[1-9]+[0-9]* or 0x0");
    }
    try {
        return new BigInteger(value.substring(2), 16);
    } catch (NumberFormatException e) {
        throw new MessageDecodingException("Negative ", e);
    }
}`

Quantity fields are expected as hex string.
so, current implementation will result in web3 and web3j throw exception.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants