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

TX counter spike #608

Closed
wants to merge 2 commits into from
Closed

TX counter spike #608

wants to merge 2 commits into from

Conversation

alpe
Copy link
Contributor

@alpe alpe commented Sep 13, 2021

🚧 SPIKE: do not merge

See #601

In this spike I have added an ante handler that counts the TX in a block and passes this down to the wasmvm Env.

  • The counter is persisted in the KV store as check/deliver/simulate processes handle their DB state accordingly
  • Simulations and external queries run with TX count 0.

Not included:

  • How the TX counter is passed to the contracts
  • Tests

Does this work for you @reuvenpo @assafmo ?

@codecov
Copy link

codecov bot commented Sep 13, 2021

Codecov Report

Merging #608 (1a0eabd) into master (50815e6) will decrease coverage by 0.03%.
The diff coverage is 57.44%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master     #608      +/-   ##
==========================================
- Coverage   60.05%   60.01%   -0.04%     
==========================================
  Files          45       48       +3     
  Lines        5212     5257      +45     
==========================================
+ Hits         3130     3155      +25     
- Misses       1860     1879      +19     
- Partials      222      223       +1     
Impacted Files Coverage Δ
x/wasm/keeper/ante.go 0.00% <0.00%> (ø)
x/wasm/types/keys.go 34.88% <ø> (ø)
x/wasm/types/ante.go 71.42% <71.42%> (ø)
app/ante.go 100.00% <100.00%> (ø)
app/app.go 84.01% <100.00%> (ø)
x/wasm/types/types.go 52.20% <100.00%> (+0.60%) ⬆️

@alpe alpe requested review from reuvenpo and ethanfrey September 13, 2021 12:32
@alpe alpe changed the title Initial spike TX counter spike Sep 13, 2021
@assafmo
Copy link
Contributor

assafmo commented Sep 13, 2021

I don't really understand why it's necessary for contracts to be aware of their in-block/in-tx position. 😅

@assafmo
Copy link
Contributor

assafmo commented Sep 13, 2021

I don't really understand why it's necessary for contracts to be aware of their in-block/in-tx position.

To clarify my comment above, we talked in a private chat with @webmaster128, @ethanfrey & @reuvenpo about a way for contract calls within the same tx to have different Envs in order for them to be able to e.g. generate unique IDs. A few of the ideas were to have a "call counter" or an in-block gas position passed down to the contract as fields in Env.

I mistakenly thought that this PR is about a "call counter" and not a "tx counter", and that's what my above comment refers to. Sorry for the misunderstanding. ♥️

@ethanfrey
Copy link
Member

Now unblocked with #617
I agree with the design, let's get a final version wired up

Copy link
Member

@ethanfrey ethanfrey left a comment

Choose a reason for hiding this comment

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

A few comments to clean it up, but the approach is good.

app/ante.go Show resolved Hide resolved
}
currentHeight := ctx.BlockHeight()
store := ctx.KVStore(a.storeKey)
var txCounter uint64 = 0
Copy link
Member

Choose a reason for hiding this comment

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

This logic seems correct but is a little confusing to follow. Maybe there is no easier way.

load the store, if there is data:

  • if same height stored, use the stored value
  • if old height stored, update stored height and set value to 0

then save the height and next counter

This may be the best way to do it, just found the flow a little confusing (maybe I am just spoiled by Rust where if can return values)

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 tried to follow the advice but there is also the case where the store is empty that requires a 0 init value. I am not sure if it would get easier by adding else blocks. Instead I have added more code comments.

}

func encodeHeightCounter(height int64, counter uint64) []byte {
return append(sdk.Uint64ToBigEndian(uint64(height)), sdk.Uint64ToBigEndian(counter)...)
Copy link
Member

Choose a reason for hiding this comment

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

super efficient.
I was expecting a protobuf type here, but this works as well.
maybe a protobuf type would be more maintainable, if we ever wanted to add a field, but I don't think that will ever be the case

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 would use a uint32 type for the counter now but otherwise leave it as it is. We can always refactor as needed. Depending on the case we another ante handler may be a better option to keep things separated. 🤷

// TXCounter return tx counter value
// Will default to `0` when not set for example in external queries or simulations
func TXCounter(ctx sdk.Context) uint64 {
val, ok := ctx.Value(contextKeyTXCount).(uint64)
Copy link
Member

Choose a reason for hiding this comment

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

what value is returned if it is never set?

I think it may be useful to differentiate between "we know it is index 0" and "no info there".
We have both on the Rust side (Option<TransactionInfo>). Maybe return (uint64, found)?

x/wasm/types/types.go Show resolved Hide resolved
Copy link
Member

@webmaster128 webmaster128 left a comment

Choose a reason for hiding this comment

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

Nice, as far as I can tell.

Can we make the counter uint32 consistently? This is what I used on the contract side:

#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
pub struct TransactionInfo {
    /// The position of this transaction in the block. The first
    /// transaction has index 0.
    ///
    /// This allows you to get a unique transaction indentifier in this chain
    /// using the pair (`env.block.height`, `env.transaction.index`).
    ///
    pub index: u32,
}

@alpe
Copy link
Contributor Author

alpe commented Sep 27, 2021

Closed in favour of #621

@alpe alpe closed this Sep 27, 2021
@alpe alpe deleted the 601-spike branch September 27, 2021 09:40
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

Successfully merging this pull request may close these issues.

4 participants