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

txngroup-deltas: Fix pointer bug copying deltas for txngroups #5375

Merged

Conversation

Eric-Warehime
Copy link
Contributor

Summary

The KvMods (and other fields in the StateDelta which are maps) have their values deleted when the roundCoW gets recycled. Because we're not copying this data out of the delta in the txn tracer, this affects the results returned by the tracer.

I've now copied all of the fields out of the maps in the StateDelta (for those that we care about returning).

Test Plan

Adding full unit tests for kvmods--other data should function similarly. This required adding some functionality to the eval test ledger which was not initially implemented during the Boxes PR.

@codecov
Copy link

codecov bot commented May 10, 2023

Codecov Report

Merging #5375 (4791b5f) into master (b988971) will increase coverage by 0.09%.
The diff coverage is 92.68%.

@@            Coverage Diff             @@
##           master    #5375      +/-   ##
==========================================
+ Coverage   55.25%   55.35%   +0.09%     
==========================================
  Files         452      452              
  Lines       63614    63643      +29     
==========================================
+ Hits        35153    35229      +76     
+ Misses      26062    26004      -58     
- Partials     2399     2410      +11     
Impacted Files Coverage Δ
ledger/eval/txntracer.go 92.59% <92.68%> (-1.64%) ⬇️

... and 20 files with indirect coverage changes

📣 We’re building smart automated test selection to slash your CI/CD build times. Learn more

@Eric-Warehime Eric-Warehime marked this pull request as ready for review May 10, 2023 19:27
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.

Nice catch, adding the box in the txntracer_test seems to show that the map is being overriden. I had a question in PR comment below

ledger/eval/txntracer.go Outdated Show resolved Hide resolved
ledger/eval/txntracer.go Show resolved Hide resolved
ledger/eval/txntracer.go Outdated Show resolved Hide resolved
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.

Looks good. One thought crosses my mind. The current box app creates the box. I'm wondering if there could be a benefit to testing some of the following - or these may be overkill:

  • modify a box with box_replace
  • delete a box with box_del
  • compose a box_create with a box_del in the same app call and/or in subsequent calls of the same group, or subsequent inner app calls.
  • similarly, composing box_replace's

@Eric-Warehime
Copy link
Contributor Author

Looks good. One thought crosses my mind. The current box app creates the box. I'm wondering if there could be a benefit to testing some of the following - or these may be overkill:

  • modify a box with box_replace
  • delete a box with box_del
  • compose a box_create with a box_del in the same app call and/or in subsequent calls of the same group, or subsequent inner app calls.
  • similarly, composing box_replace's

I can add a bit more, but in general none of this code cares what the TEAL code is doing, just that it properly conveys the deltas associated with it. And the fact that KvMods are present pretty much means all KvMod opcode deltas will be present as well.

The inner txn box mods would probably be worthwhile to test. Potentially having subsequent updates to the same box as well I guess?

@tzaffi
Copy link
Contributor

tzaffi commented May 11, 2023

I can add a bit more, but in general none of this code cares what the TEAL code is doing, just that it properly conveys the deltas associated with it. And the fact that KvMods are present pretty much means all KvMod opcode deltas will be present as well.

Totally up to you. If you're viewing the KvMods as a "black box" in which case the current scenario proves that the PR reveals the black box as is, then no further tests are required. But if the logic could be tricked into believing that there aren't any txndelta's when actually there were (e.g. by piling on changes, or reversing them) then another test case would be called for.

The inner txn box mods would probably be worthwhile to test. Potentially having subsequent updates to the same box as well I guess?

Yeah, in the past, the inner txns seemed to always be the most error prone due to recursion.

algochoi
algochoi previously approved these changes May 11, 2023
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.

LGTM, thanks for addressing comments!

@Eric-Warehime
Copy link
Contributor Author

@tzaffi Yep, for the most part I'd like to treat it as an opaque operation, but that operation was only intended to be correct at the block level and not necessarily at the txn-group level so it's worthwhile to add more tests. I've added a box_del call in an inner txn to the test.

Let me know if you feel like we really need to test anything else that's critical path w/r/t the deltas here.

@Eric-Warehime Eric-Warehime requested a review from tzaffi May 11, 2023 16:43
Comment on lines +321 to +324
"bx:\x00\x00\x00\x00\x00\x00\x03\xefgoodbyebox": {
OldData: nil,
Data: nil,
},
Copy link
Contributor

@tzaffi tzaffi May 11, 2023

Choose a reason for hiding this comment

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

So this ghost of boxes past is picked up because the box was created then deleted?

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, nil for the Data field represents a deleted box.

It is weird that the OldData field is 0 bytes for hellobox but nil for goodbyebox even though both of those were created in the group. It could just be a matter of how I've implemented LookupKv in the test ledger though so the actual ledger might not act in the same way.

tzaffi
tzaffi previously approved these changes May 11, 2023
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.

LGTM

algochoi
algochoi previously approved these changes May 11, 2023
jannotti
jannotti previously approved these changes May 11, 2023
Copy link
Contributor

@jannotti jannotti left a comment

Choose a reason for hiding this comment

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

I'm willing to merge this, let me know if you want to do anything about the things I mentioned.

@jasonpaulos should also see it though - it feels like you're both addressing some copying issues right now.

Comment on lines 274 to 275
ApprovalProgram: []byte{0x08, 0x80, 0x08, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x62, 0x6f, 0x78, 0x81, 0x0a, 0xb9, 0x48, 0x81, 0x01},
ClearStateProgram: []byte{0x08, 0x81, 0x01},
Copy link
Contributor

Choose a reason for hiding this comment

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

I guess you didn't put these here originally, but the fact that we're editing hex bytecode here seems bad. I assume this is a compiled program, can we use logic.AssembleString so it makes more sense?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Updated. I actually did write those originally, just not in this PR. I wasn't aware that this was the proper way to encode these.

@@ -600,6 +600,7 @@ type evalTestLedger struct {
rewardsPool basics.Address
latestTotals ledgercore.AccountTotals
tracer logic.EvalTracer
boxes map[string][]byte
Copy link
Contributor

Choose a reason for hiding this comment

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

Every test that uses this evalTestLedger creeps me out. It is a mock that maybe has the same behaviour as a real ledger, and maybe not. So every time we extend it to try to do more, it feels even more as though every test should be converted to use a real ledger. DoubleLedger and TestConsensusRange have some real benefits in terms of accuracy and testing across changes in old versions.

I'm not going to hold up this PR, but we have to wean ourselves off this thing.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah I agree the actual implementation of the test ledger is pretty far from the actual ledger. It does seem difficult to mock since the data retrieved in the actual ledger hits the caches (trackers) first and then disk if the cache misses.

I haven't looked into the DoubleLedger or TestConsensusRange, but I will do next time I need to test things requiring the ledger.

Copy link
Contributor

Choose a reason for hiding this comment

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

Using real ledger will make all dependent tests very slow. I guess we need just one unified mock with some default implementation and let embedders to override methods they care about

Comment on lines +733 to +735
// The test ledger only has one view of the value of a box--no rnd based retrieval is implemented currently
val, _ := ledger.boxes[key]
return val, nil
Copy link
Contributor

@jannotti jannotti May 11, 2023

Choose a reason for hiding this comment

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

This is the kind of craziness I'm talking about. Shouldn't we use a real ledger, and not constantly make little updates to approximate its behavior here?

@Eric-Warehime Eric-Warehime dismissed stale reviews from jannotti and algochoi via b2c731d May 11, 2023 19:17
jasonpaulos
jasonpaulos previously approved these changes May 11, 2023
ledger/eval/txntracer.go Outdated Show resolved Hide resolved
@@ -600,6 +600,7 @@ type evalTestLedger struct {
rewardsPool basics.Address
latestTotals ledgercore.AccountTotals
tracer logic.EvalTracer
boxes map[string][]byte
Copy link
Contributor

Choose a reason for hiding this comment

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

Using real ledger will make all dependent tests very slow. I guess we need just one unified mock with some default implementation and let embedders to override methods they care about

@@ -223,12 +311,8 @@ int 1`,
Addr: addrs[0],
Params: ledgercore.AppParamsDelta{
Params: &basics.AppParams{
ApprovalProgram: []byte{0x06, 0x80, 0x01, 0x61, 0xb0, 0xb1, 0x81, 0x06, 0xb2, 0x10, 0x81, 0x00, 0xb2, 0x19, 0x80, 0x07,
Copy link
Contributor

Choose a reason for hiding this comment

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

nooo... we like reading bytecode

algorandskiy
algorandskiy previously approved these changes May 11, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants