Skip to content
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

Update internal transaction trace. #88

Closed
ChenxingLi opened this issue Dec 23, 2021 · 2 comments
Closed

Update internal transaction trace. #88

ChenxingLi opened this issue Dec 23, 2021 · 2 comments

Comments

@ChenxingLi
Copy link
Collaborator

ChenxingLi commented Dec 23, 2021

A recent PR changes the trace of transaction trace. The changes are described as follows.

中文摘要

  • trace 列表的每个 item 增加一个 field "valid". "valid"false 时表示该条 trace 因为 revert 等原因没有改变 state.
  • Gas 费用的收取和存储押金的收取、退还将产生 trace. 类型为 "internal_transfer_action".
  • Type 为 ”internal_transfer_action“ 的 trace 项添加两个 field, "fromPocket" 和 "toPocket". 只有当 "fromPocket" 等于 "balance" 时,才意味着 "from" 的余额被修改。

The "valid" field

If the inner message call triggers an error and the error is caught by the outside contract, the whole transaction could also succeed, but the effects of the inner message call are reverted. The traces of the reverted message call will also be retained for debugging usage.

Here, we add a new field "valid" to indicate whether the corresponding trace is reverted.

Trace for gas payment.

Any transaction bumping nonce during execution will generate one or two traces with type "internal_transfer_action" to indicate gas payment and gas refund.

Consider a transaction has gas limit 40000 and gas price 3 Drip.

For gas payment, if the transaction is sponsored, the trace will be

{
    "action": {
        "from": <contract_address>,
        "fromPocket": "sponsor_balance_for_gas",
        "to": <zero_address>,
        "toPocket": "gas_payment",
        "value": 120000, 
    }
    "type": "internal_transfer_action"
    ......
}

If the transaction is not sponsored, the trace will be

{
    "action": {
        "from": <sender_address>,
        "fromPocket": "balance",
        "to": <zero_address>,
        "toPocket": "gas_payment",
        "value": 120000, 
    }
    "type": "internal_transfer_action"
    ......
}

This should be the first trace of most transactions.

After execution, if this transaction costs 25000 gas, up to 1/4 of gas limit, i.e., 10000 gas (30000 Drip when gas price = 3) will be refunded, then it will generate a trace

{
    "action": {
        "from": <zero_address>,
        "fromPocket": "gas_payment",
        "to": ...,
        "toPocket": ...,
        "value": 30000, 
    },
    "type": "internal_transfer_action",
    ...
}

Trace for storage collateral.

Consider a transaction collateralize 10 Drip (it can not happen in a real Conflux system, just for example).

If the transaction is sponsored,

{
    "action": {
        "from": <contract_address>,
        "fromPocket": "sponsor_balance_for_collateral",
        "to": <contract_address>,
        "toPocket": "storage_collateral",
        "value": 10, 
    },
    "type": "internal_transfer_action",
    ...
}

If the transaction is not sponsored,

{
    "action": {
        "from": <sender_address>,
        "fromPocket": "balance",
        "to": <sender_address>,
        "toPocket": "storage_collateral",
        "value": 10, 
    },
    "type": "internal_transfer_action",
    ...
}

When releasing storage, the value will be returned to the same route.

Changes in the sponsorship (example)

When a user adds sponsor balance for gas for a contract, the trace will be

Before change

{
    "action": {
        "from": <sender_address>,
        "to": <internal_contract_for_sponsorship>, // 0x088800...01
        "value": ...,
        ...
    },
    "type": "call",
    ...
}

After change

{
    "action": {
         // call type trace has no fromPocket and toPocket field. Because the pocket is always "balance". 
        "from": <sender_address>,
        "to": <internal_contract_for_sponsorship>, // 0x088800...01
        "value": ...,
        ...
    },
    "type": "call",
    ...
}
{
    "action": {
        "from": <internal_contract_for_sponsorship>, // 0x088800...01
        "fromPocket": "balance",
        "to": <contract_address>,
        "toPocket": "sponsor_balance_for_gas"
        "value": ...,
        ...
    },
    "type": "internal_transfer_action",
    ...
}

Now you can know which contract is sponsored from the trace.

Changes in the staking (example)

When a user stakes, the trace will be

Before change

{
    "action": {
        "from": <sender_address>,
        "to": <internal_contract_for_staking>, // 0x088800...02
        "value": ...,
        ...
    },
    "type": "internal_transfer_action",
    ...
}

After change

{
    "action": {
        "from": <sender_address>,
        "fromPocket": "balance",
        "to": <sender_address>, 
        "toPocket": "staking_balance",
        "value": ...,
        ...
    },
    "type": "internal_transfer_action",
    ...
}

Indicator for kill contract

Each time a contract is killed, it will produce such a trace,

{
    "action": {
        "from": <contract_address>,
        "fromPocket": "balance",
        "to": <zero_address>, 
        "toPocket": "mint_burn",
        "value": ...,
        ...
    },
    "type": "internal_transfer_action",
    ...
}

Changes in integrity constraints

Before change

  • The balance increasing (or decreasing) of an address (except the internal contract) during transaction execution corresponds to a trace whose "to" (or "from") is this address.

After change

  • The balance increasing (or decreasing) of an address (all the address) during transaction execution corresponds to a trace whose "to" (or "from") is this address and "toPocket" (or "fromPocket") is "balance". (Note: for trace type except "interal_transfer_action", the "fromPocket" and "toPocket" equal to "balance" implicitly.)
  • The staking balance/collateral balance/sponsor balance for gas/sponsor balance for collateral increasing (or decreasing) of an address during transaction execution corresponds to an internal_transfer type trace whose "to" (or "from") is this address and "toPocket" (or "fromPocket") is "sponsor_balance"/"storage_collateral"/"sponsor_balance_for_gas"/"sponsor_balance_for_collateral".

Specification for pocket

In Conflux, each account could have several pockets to store CFX.

  • balance
  • staking_balance
  • storage_collateral
  • sponsor_balance_for_gas
  • sponsor_balance_for_collateral

The fromPocket field and toPocket field could be one of them.

Besides these five values, the "pocket" could be two special values "mint_burn" and "gas_payment".

  • fromPocket = "mint_burn": mint CFX, e.g., generate staking interest
  • toPocket = "mint_burn": burn CFX, e.g., when a contract is killed, its staking balance will be burnt.
  • fromPocket = "gas_payment": gas payment, usually equals to gas_price * gas_limit
  • toPocket = "gas_payment": gas refund after transaction execution.
@wangdayong228
Copy link

wangdayong228 commented Dec 27, 2021

Reference:

Paragraph of Changes in integrity constraints -> After change

The staking balance/collateral balance/sponsor balance for gas/sponsor balance for collateral increasing (or decreasing) of an address during transaction execution corresponds to an internal_transfer type trace whose "to" (or "from") is this address and "toPocket" (or "fromPocket") is "sponsor_balance"/"storage_collateral"/"sponsor_balance_for_gas"/"sponsor_balance_for_gas".

Comment:
Should the last word sponsor_balance_for_gas be sponsor_balance_for_collateral ?

@ChenxingLi
Copy link
Collaborator Author

Fixed

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

No branches or pull requests

2 participants