-
Notifications
You must be signed in to change notification settings - Fork 471
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
txngroup-deltas: Fix pointer bug copying deltas for txngroups #5375
Conversation
Codecov Report
@@ 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
... and 20 files with indirect coverage changes 📣 We’re building smart automated test selection to slash your CI/CD build times. Learn more |
There was a problem hiding this 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
There was a problem hiding this 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 abox_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? |
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.
Yeah, in the past, the inner txns seemed to always be the most error prone due to recursion. |
There was a problem hiding this 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!
@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 Let me know if you feel like we really need to test anything else that's critical path w/r/t the deltas here. |
"bx:\x00\x00\x00\x00\x00\x00\x03\xefgoodbyebox": { | ||
OldData: nil, | ||
Data: nil, | ||
}, |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
There was a problem hiding this 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.
ledger/eval/txntracer_test.go
Outdated
ApprovalProgram: []byte{0x08, 0x80, 0x08, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x62, 0x6f, 0x78, 0x81, 0x0a, 0xb9, 0x48, 0x81, 0x01}, | ||
ClearStateProgram: []byte{0x08, 0x81, 0x01}, |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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
// 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 |
There was a problem hiding this comment.
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?
@@ -600,6 +600,7 @@ type evalTestLedger struct { | |||
rewardsPool basics.Address | |||
latestTotals ledgercore.AccountTotals | |||
tracer logic.EvalTracer | |||
boxes map[string][]byte |
There was a problem hiding this comment.
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, |
There was a problem hiding this comment.
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
4791b5f
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.