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

AVM: Make txn FirstValidTime and block opcode available in logicsigs #4371

Merged
merged 12 commits into from
Aug 9, 2022

Conversation

jannotti
Copy link
Contributor

@jannotti jannotti commented Aug 8, 2022

Thread the ledger into the GroupContext so it can be used during LogicSig evaluation.

To limit the chance of stateless/stateful bugs, the Ledger is "narrowed" to a LedgerForSignature interface that only exposes the past block headers.

@jannotti jannotti changed the title Make txn FirstValidTime and block opcode available in logicsigs AVM: Make txn FirstValidTime and block opcode available in logicsigs Aug 8, 2022
@codecov
Copy link

codecov bot commented Aug 8, 2022

Codecov Report

Merging #4371 (aee4243) into master (d7ed271) will decrease coverage by 0.06%.
The diff coverage is 60.00%.

@@            Coverage Diff             @@
##           master    #4371      +/-   ##
==========================================
- Coverage   55.28%   55.22%   -0.07%     
==========================================
  Files         395      395              
  Lines       50352    50367      +15     
==========================================
- Hits        27838    27814      -24     
- Misses      20119    20157      +38     
- Partials     2395     2396       +1     
Impacted Files Coverage Δ
cmd/goal/clerk.go 8.75% <0.00%> (-0.02%) ⬇️
data/txHandler.go 0.00% <0.00%> (ø)
node/node.go 23.01% <0.00%> (-2.39%) ⬇️
data/transactions/verify/txn.go 43.85% <50.00%> (-1.03%) ⬇️
data/transactions/logic/eval.go 89.57% <76.92%> (+0.06%) ⬆️
cmd/tealdbg/local.go 73.95% <100.00%> (+0.09%) ⬆️
daemon/algod/api/server/v2/dryrun.go 70.82% <100.00%> (+0.08%) ⬆️
data/transactions/logic/assembler.go 85.16% <100.00%> (ø)
ledger/internal/eval.go 68.65% <100.00%> (+0.04%) ⬆️
ledger/tracker.go 71.79% <0.00%> (-4.71%) ⬇️
... and 9 more

📣 Codecov can now indicate which changes are the most critical in Pull Requests. Learn more

@@ -1483,6 +1483,7 @@ type evalTxValidator struct {
txcache verify.VerifiedTransactionCache
block bookkeeping.Block
verificationPool execpool.BacklogPool
ledger logic.LedgerForLogic
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't see where this field is ever assigned

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Agreed. What on earth.

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 seems as though LogicSigs can be evaluated along two paths, and I've clearly not fixed the path that uses evalTxValidator. Before I fix it, I'd like to find or write failing tests.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@algorandskiy do we have tests evalTxValidator? It looks to me like it's use in txn validation, so I don't understand how my code is passing most tests, including e2e tests, without a way to get block headers.

Copy link
Contributor Author

@jannotti jannotti Aug 8, 2022

Choose a reason for hiding this comment

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

I suppose the only ones that would fail are ones with a block or txn FirstValidTime in them (since only they access SigLedger). But we have an e2e test that does that, and it passes.

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'm committing a check in EvalSignature for SigLedger == nil. I suppose we should have it anyway, but my goal is to see if maybe we do have a test that exercises this code, but it was not failing because it was not using the new opcodes, so it didn't complain about the nil SigLedger.

testApp(t, "int 4294967299; block BlkSeed; len; int 32; ==", ep) // current - 1
testApp(t, "int 4294967300; block BlkSeed; len; int 32; ==", ep,
"not available") // can't get current round's blockseed
testApp(t, "int 4294967300; block BlkSeed; len; int 32; ==", ep)
Copy link
Contributor

Choose a reason for hiding this comment

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

this is confusing.
cow.Round() is always the current (latest +1). So the old test is valid and the new one is not.

Copy link
Contributor

Choose a reason for hiding this comment

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

my understanding is we supply cow to contracts and ledger to logicsig. But the same Round() method returns the different values.
Maybe one should be Latest() and another 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.

I think I know what's going on now. I added a Round() method to ledger.Ledger, so I could use it as a LedgerForSignature. I should have used Latest()+1, but used Latest(). I need to get them doing the same thing, and then the test will go back to what it was.

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 should be back to making sense.

@@ -4848,7 +4861,7 @@ func (cx *EvalContext) availableRound(r uint64) (basics.Round, error) {
if firstAvail > cx.txn.Txn.LastValid || firstAvail == 0 { // early in chain's life
firstAvail = 1
}
current := cx.Ledger.Round()
current := cx.SigLedger.Round()
round := basics.Round(r)
if round < firstAvail || round >= current {
Copy link
Contributor

Choose a reason for hiding this comment

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

this is interesting, Round() is either current, or latest, depending on a context, and the condition round >= current is technically correct for both contexts but looks as a maintainability problem.

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've changed it so that regardless of how the SigLedger is supplied (either as a copy of Ledger, or on its own for LogicSig evaluation) Round() is Latest()+1. I think that is fairly good, although I remain worried about transactions added to a long queue that will be dropped asking for a header that doesn't exist yet.

@jannotti
Copy link
Contributor Author

jannotti commented Aug 8, 2022

I've removed Round() from SigLedger. The rule for what blocks are available is now simpler and depends only on the transaction, which seems nice for LogicSigs.

But the big mystery is how to get a test to fail for the clearly erroneous way the evalTxValidator is initialized in ledger/internal/eval.go's Eval

Copy link
Contributor

@algorandskiy algorandskiy left a comment

Choose a reason for hiding this comment

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

LGTM. One comment about Round -> round.
I'll take another look on morning

data/transactions/logic/eval.go Show resolved Hide resolved
ledger/internal/applications.go Outdated Show resolved Hide resolved
@jannotti jannotti marked this pull request as ready for review August 9, 2022 13:09
@jannotti jannotti requested a review from algorandskiy August 9, 2022 13:09
@jannotti jannotti requested a review from jasonpaulos August 9, 2022 13:09
testApp(t, "int 4294967299; block BlkSeed; len; int 32; ==", ep) // current - 1

// These first two tests show that current-1 is not available now, though a
// resonable extension is to allow such access for apps (not sigs).
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: resonable -> reasonable

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