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

eval: Add block hooks to eval tracer #5303

Merged
merged 5 commits into from Apr 19, 2023

Conversation

Eric-Warehime
Copy link
Contributor

Summary

Adds BeforeBlock and AfterBlock hooks to the EvalTracer interface.

This should be a no-op for most of the things which Simulate is trying to do, but gives the Tracer a sense of which Block a given set invocations covers. That's important since the EvalContext and EvalParams from what I can tell don't have a deterministic way of looking at which round they're evaluating for without direct access to the BlockEvaluator itself.

Test Plan

Updated existing test to ensure calls are properly made during eval lifecycle.

@@ -152,6 +152,7 @@ int 1`,
mocktracer.AfterOpcode(false),
mocktracer.AfterProgram(logic.ModeSig, false),
// Txn evaluation
mocktracer.BeforeBlock(block.Block().Round()),
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This order was surprising to me, but because LogicSig verification happens before the Txns in the block get evaluated the BeforeBlock call will happen after LogicSig verification.

@Eric-Warehime Eric-Warehime marked this pull request as ready for review April 14, 2023 00:42
Copy link
Contributor

@algochoi algochoi left a comment

Choose a reason for hiding this comment

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

Looks pretty reasonable to me - is the plan to compare some sort of deltas between the two before/after block headers or simply to extract certain information from it, e.g. round num?

@Eric-Warehime
Copy link
Contributor Author

Looks pretty reasonable to me - is the plan to compare some sort of deltas between the two before/after block headers or simply to extract certain information from it, e.g. round num?

The reason I want it currently is to get the round num, but I thought it would be useful to have the whole header just in case we need other data from it as well.

You can take a look at #5297 to see how the Tracer I'm writing needs something like this. It's still in draft though so there's a bunch of unfinished stuff in there.

Copy link
Contributor

@ahangsu ahangsu left a comment

Choose a reason for hiding this comment

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

Just took a quick pass, and I think the PR might be interesting on simulation aspect (if I read the PR correctly), but might be hard (or unreasonable) to do. I was thinking:

If we are overloading some runtime config in EvalContext for certain opcodes during simulating multiple txn-groups, then the current implementation is to overload the configs inside cx *EvalContext during BeforeTxnGroup.

I think it might be better to just overload config once in BeforeBlock, assuming the multiple txn-groups are falling into same block, and EvalContext can be maintained through more than one txn-groups.

But that might be not the purpose of this PR, and EvalContext is not avail on block level?

Copy link
Contributor

@tzaffi tzaffi left a comment

Choose a reason for hiding this comment

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

Seems like a safe PR, but I don't see the big picture yet for its impact. I left a couple of commentary nits and a question.

Round basics.Round
}

// BeforeBlock creates a new Event with the type BeforeBlockEvent
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
// BeforeBlock creates a new Event with the type BeforeBlockEvent
// BeforeBlock creates a new Event with the type BeforeBlockEvent for a particular round

ignorable nit

@@ -833,13 +834,14 @@ func (l *Ledger) VerifiedTransactionCache() verify.VerifiedTransactionCache {
// provides a cap on the size of a single generated block size, when a non-zero value is passed.
// If a value of zero or less is passed to maxTxnBytesPerBlock, the consensus MaxTxnBytesPerBlock would
// be used instead.
func (l *Ledger) StartEvaluator(hdr bookkeeping.BlockHeader, paysetHint, maxTxnBytesPerBlock int) (*eval.BlockEvaluator, error) {
func (l *Ledger) StartEvaluator(hdr bookkeeping.BlockHeader, paysetHint, maxTxnBytesPerBlock int, tracer logic.EvalTracer) (*eval.BlockEvaluator, error) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Can we add an explanation of the optional tracer param as well?

Comment on lines +294 to +295
tracer := &mocktracer.Tracer{}
eval, err := l.StartEvaluator(newBlock.BlockHeader, 0, 0, tracer)
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this test being modified purely because there is now a prefered way to attach a tracer? I'm trying to understand what new behavior is being tested.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It's both the new way of attaching the tracer, but also the new Before/After Block hooks. Here I've modified how the tracer is attached, and below you can see I've added the mocktracer.AfterBlock(eval.block.Round()), event to assert that the tracer was called as expected.

Copy link
Member

@jasonpaulos jasonpaulos left a comment

Choose a reason for hiding this comment

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

Looks pretty good. I just have minor comments

ledger/simulation/simulator.go Show resolved Hide resolved
ledger/eval/eval_test.go Show resolved Hide resolved
data/transactions/logic/tracer.go Show resolved Hide resolved
@Eric-Warehime
Copy link
Contributor Author

Just took a quick pass, and I think the PR might be interesting on simulation aspect (if I read the PR correctly), but might be hard (or unreasonable) to do. I was thinking:

If we are overloading some runtime config in EvalContext for certain opcodes during simulating multiple txn-groups, then the current implementation is to overload the configs inside cx *EvalContext during BeforeTxnGroup.

I think it might be better to just overload config once in BeforeBlock, assuming the multiple txn-groups are falling into same block, and EvalContext can be maintained through more than one txn-groups.

But that might be not the purpose of this PR, and EvalContext is not avail on block level?

I didn't intend for the block evaluator to carry state across txns/groups like that, but I guess you could do it if you wanted. The EvalContext doesn't have anything to do with the ledger's idea of starting and finishing block evaluation though. It's just involved in contract evaluation.

@Eric-Warehime
Copy link
Contributor Author

Looks pretty reasonable to me - is the plan to compare some sort of deltas between the two before/after block headers or simply to extract certain information from it, e.g. round num?

Right now it's just to extract the round from them--I've included the whole header to have a more generalized interface.

Copy link
Member

@jasonpaulos jasonpaulos left a comment

Choose a reason for hiding this comment

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

LGTM

Copy link
Contributor

@algochoi algochoi left a comment

Choose a reason for hiding this comment

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

Minor question below but looks good

data/transactions/logic/tracer.go Show resolved Hide resolved
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants