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: incentive opcodes #5984

Merged
merged 133 commits into from
May 15, 2024
Merged
Show file tree
Hide file tree
Changes from 127 commits
Commits
Show all changes
133 commits
Select commit Hold shift + click to select a range
a6a51db
Implements "Mining" - diverting a portion of fees to proposers
jannotti Sep 15, 2023
84ee996
Add min and max to receive block incentives
jannotti Nov 28, 2023
c3bc1c8
Stop checking for incentive payouts in e2e subs.
jannotti Nov 29, 2023
1d9b337
Add IncentiveEligible field to accounts.
jannotti Nov 30, 2023
1993a9f
Maintain and use the acct.Incentiveligible flag
jannotti Nov 30, 2023
b717df6
Test assembly of new block fields
jannotti Dec 21, 2023
00de010
year
jannotti Jan 9, 2024
1aa9072
it's v11 now
jannotti Jan 9, 2024
854d149
Adds LastProposed fields, and logic for checking absenteeism
jannotti Sep 26, 2023
cd40d74
Remove basics.Suspended as an explicit account state
jannotti Jan 9, 2024
8a6bc20
Go e2e test showing suspension and proposal to come back online
jannotti Jan 14, 2024
49c24de
If a suspended account proposes, bring it back online.
jannotti Jan 16, 2024
be105aa
Suspensions turns off IncentiveEligible
jannotti Jan 18, 2024
b6578aa
Don't consider pre-existing accounts absent
jannotti Jan 18, 2024
f7b87bb
Merge remote-tracking branch 'upstream/master' into absenteeism-2
jannotti Jan 24, 2024
09f72db
Perform bonus payments, with exponential decay
jannotti Jan 24, 2024
cce9432
Show node can re-reg to become incentive eligible again
jannotti Jan 26, 2024
7e0d283
Typo level fixes
jannotti Jan 27, 2024
8b7946f
Make test (almost) unflakable
jannotti Jan 29, 2024
1996bce
Some CR updates
jannotti Jan 30, 2024
2c5a66a
Remove `WithSeed` from non-validated Block
jannotti Jan 30, 2024
ba42ba8
Implement "challenges"
jannotti Jan 31, 2024
06c10c1
CR fixes
jannotti Jan 31, 2024
794dcea
Add BlkBonus assembly test
jannotti Jan 31, 2024
ee9a623
Account for new fields in header
jannotti Jan 31, 2024
59b4f98
Simplify decay code, show first year behaviour
jannotti Jan 31, 2024
1f3e485
forgotten partitiontest
jannotti Jan 31, 2024
eb923da
Completed a comment
jannotti Jan 31, 2024
b2f7691
Tidying and testing
jannotti Feb 1, 2024
80410fe
bonus rate change tests
jannotti Feb 1, 2024
b69c021
Turn on block bonuses in vFuture
jannotti Feb 1, 2024
fd4ccaf
Relocate suspension_test.go to prep for adding similar incentives
jannotti Feb 1, 2024
3959e1d
Add e2e test for mining and bonuses
jannotti Feb 2, 2024
bb401cf
pass up the error
jannotti Feb 5, 2024
316083f
WithSeed -> WithProposal
jannotti Feb 5, 2024
46470f7
Many CR changes, most notably using consensus params
jannotti Feb 7, 2024
762a77a
Missed a change
jannotti Feb 7, 2024
a05e317
Better comment about overflow
jannotti Feb 7, 2024
c0cfdef
Lint related comments
jannotti Feb 7, 2024
c26ca5b
ok reviewdog, you win
jannotti Feb 8, 2024
0ed15ec
CR changes
jannotti Feb 9, 2024
23b12cf
Some missed function parameter changes
jannotti Feb 9, 2024
5743edf
spelling
jannotti Feb 9, 2024
69c982e
missing word
jannotti Feb 9, 2024
8aa85e9
Adjust test for bonus payout
jannotti Feb 12, 2024
64b2103
Record the block payout explicitly
jannotti Mar 4, 2024
34f1ede
Fixups for moving some functionality to agreemnet
jannotti Mar 5, 2024
693ba61
max size change for proposerPayout
jannotti Mar 6, 2024
6db9d51
Correctly learn consensus params for current proposal.
jannotti Mar 7, 2024
4eac136
Fixups to get the separation between eval and agreement right
jannotti Mar 8, 2024
44d120f
Don't ignore err
jannotti Mar 11, 2024
43940e9
Fixup ledger tests for proposer presence
jannotti Mar 11, 2024
dfe7bb6
comment wording
jannotti Mar 11, 2024
bee6bdd
feature flag the header properly
jannotti Mar 12, 2024
aee989c
Comment change and pointless code removal
jannotti Mar 14, 2024
a8c1d9b
Fix unit test for eligibility test in blance round
jannotti Mar 14, 2024
7abf6b4
suspension test updates
jannotti Mar 15, 2024
7dbd497
Reduce duplicative calls
jannotti Mar 18, 2024
13af5f0
Comment clarification
jannotti Mar 20, 2024
0aa7d5f
sanity check
jannotti Mar 20, 2024
c49946f
CR updates
jannotti Mar 20, 2024
76af3a3
Absent list generation tests
jannotti Mar 20, 2024
a61a0ef
Add methods for some reason
jannotti Mar 20, 2024
74ede81
WithProposER
jannotti Mar 20, 2024
fd1c88b
Copy IncentiveEligible in ledgercore function
jannotti Mar 20, 2024
9d536a7
comment updates
jannotti Mar 20, 2024
a7e7010
More explicitly set the returned stackValue
jannotti Mar 20, 2024
1b0d633
more friendly fire from adding methods
jannotti Mar 20, 2024
f64c143
Move the mining and bonus stuff into consensus
jannotti Mar 21, 2024
53b9cca
lint docs
jannotti Mar 21, 2024
613d7d4
spelling
jannotti Mar 21, 2024
961ae74
make msgp
jannotti Mar 21, 2024
88e7192
collateral damage
jannotti Mar 21, 2024
1ec4f31
Remove "mining" wording from comments and variable names
jannotti Mar 21, 2024
dcb4636
func, field, whatever
jannotti Mar 22, 2024
648f95e
Pass the actual proposer into payoutEligible, even before payouts
jannotti Mar 25, 2024
9c8211c
Trying to track down a failure
jannotti Mar 25, 2024
c054b3c
split ValidatedBlock and AssembledBlock interfaces
cce Mar 27, 2024
6305819
fix new tests
cce Mar 27, 2024
216ea21
checkpoint better testing before n+1 to n
jannotti Mar 28, 2024
e0658cd
bonus constant changes
jannotti Mar 28, 2024
b3c26ca
Make the proposer payouts happen in same block they are proposed.
jannotti Mar 29, 2024
73798d1
No idea why this is failing
jannotti Mar 29, 2024
a914ee1
Don't save the deltas after generating a proposal
jannotti Mar 29, 2024
e82769e
Merge branch 'absenteeism' into absenteeism-split-assembledblock
jannotti Mar 29, 2024
0ef3056
Merge pull request #19 from cce/absenteeism-split-assembledblock
jannotti Mar 29, 2024
4e2313a
correct type in merge conflict resolution
jannotti Mar 29, 2024
82263e1
Merge branch 'master' into absenteeism
jannotti Mar 29, 2024
2c40125
first step of applying unfinishedBlock changes from algorand/go-algor…
cce Apr 3, 2024
f2c4f29
add ledgercore.UnfinishedBlock and provide VotingAccountChecker to tr…
cce Apr 4, 2024
43f74e5
wire up ledgercore.UnfinishedBlock to node AssembleBlock implementati…
cce Apr 4, 2024
0e3034a
fix tests & generator
cce Apr 4, 2024
5dbe3c1
update remaining broken tests to use GenerateBlock and MakeValidatedB…
cce Apr 4, 2024
b7c7fe0
move MakeAccountManager to be above MakeTransactionPool
cce Apr 5, 2024
8893086
CR changes
jannotti Apr 9, 2024
906c8aa
rename VotingAccountChecker => Supplier
cce Apr 9, 2024
d8ad692
rename ue, ve, to ub, pb
cce Apr 9, 2024
6551096
don't assign ProposableBlock to ValidatedBlock in agreement tests
cce Apr 9, 2024
7ac7e00
Merge remote-tracking branch 'cce/absenteeism-unfinishedblock' into a…
jannotti Apr 10, 2024
72957a0
Don't pay closed proposers.
jannotti Apr 10, 2024
569a48e
linter
jannotti Apr 10, 2024
6bff639
Prevent payouts to closed account
jannotti Apr 11, 2024
aceef41
Fixup for rule that proposer must exist to be paid
jannotti Apr 11, 2024
6540c05
Insert paranoid debug check to investivate failure in CI
jannotti Apr 11, 2024
73fff7b
very old typo fix
jannotti Apr 12, 2024
82e244d
Pavel CR
jannotti Apr 12, 2024
c27f7b3
explain the paranoia differently after interface changes
jannotti Apr 12, 2024
58a70e6
Tidy up endOfBlock()
jannotti Apr 12, 2024
a46890d
Reduce "shim types", introduce agreement.Block
jannotti Apr 12, 2024
8baf0f2
Removed XXX in favor of explaining that we are skipping agreement
jannotti Apr 12, 2024
7b1560d
CR cleanup
jannotti Apr 16, 2024
015379b
Make it clearer where the delays come from
jannotti Apr 16, 2024
e0c5d4f
mining -> payouts
jannotti Apr 16, 2024
f1082f5
Leave lookback at 320 for suspension test
jannotti Apr 17, 2024
0265066
Merge pull request #21 from jannotti/agreement-block
jannotti Apr 18, 2024
ba5efda
Accomodate talking to slow clients
jannotti Apr 18, 2024
40ce14a
add mismatched proposer check to increase coverage a tiny bit
cce Apr 19, 2024
1037ad5
Apply suggestions from code review
cce Apr 19, 2024
87a20c5
exercise inability to pay from fee sink
jannotti Apr 22, 2024
7ddccf3
Simplifiy tests. No "current" test, and no mockBalances
jannotti Apr 22, 2024
480f0f9
Typo
jannotti Apr 23, 2024
762e15b
comment
jannotti Apr 23, 2024
3d2fbc4
Ensure only the address we thought would get suspended did.
jannotti Apr 23, 2024
41d572f
Merge remote-tracking branch 'upstream/master' into absenteeism
jannotti Apr 23, 2024
f5c1fd6
voter_params_get to examine online stake of accounts
jannotti Apr 4, 2024
0a95d6b
Add `online_stake` opcode
jannotti Apr 5, 2024
4f7c3f6
More comprehensive testing of global opcode
jannotti Apr 9, 2024
e1a3cc6
typos
jannotti Apr 29, 2024
03f694f
clarity on voter params get
jannotti Apr 29, 2024
68ccf6a
Return zeros when account is offline
jannotti Apr 29, 2024
8e306a6
Test `voter_params_get` on a suspended account
jannotti Apr 30, 2024
64ff41b
CR rename
jannotti May 8, 2024
9743a9f
Correct comment
jannotti May 14, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion agreement/proposal.go
Original file line number Diff line number Diff line change
Expand Up @@ -277,7 +277,7 @@ func verifyProposer(p unauthenticatedProposal, ledger LedgerReader) error {
// the header lacks it, the returned balanceRecord will be the right record.
func payoutEligible(rnd basics.Round, proposer basics.Address, ledger LedgerReader, cparams config.ConsensusParams) (bool, basics.OnlineAccountData, error) {
// Check the balance from the agreement round
balanceRound := balanceRound(rnd, cparams)
balanceRound := BalanceRound(rnd, cparams)
balanceRecord, err := ledger.LookupAgreement(balanceRound, proposer)
if err != nil {
return false, basics.OnlineAccountData{}, err
Expand Down
2 changes: 1 addition & 1 deletion agreement/pseudonode.go
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,7 @@ func (n *asyncPseudonode) loadRoundParticipationKeys(voteRound basics.Round) []a
n.participationKeys = nil
return nil
}
balanceRound := balanceRound(voteRound, cparams)
balanceRound := BalanceRound(voteRound, cparams)

// measure the time it takes to acquire the voting keys.
beforeVotingKeysTime := time.Now()
Expand Down
2 changes: 1 addition & 1 deletion agreement/pseudonode_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -449,7 +449,7 @@ func TestPseudonodeLoadingOfParticipationKeys(t *testing.T) {
for rnd := basics.Round(3); rnd < 1000; rnd += 43 {
keyManagerProxy.target = func(votingRound, balanceRnd basics.Round) []account.ParticipationRecordForRound {
require.Equal(t, rnd, votingRound)
require.Equal(t, balanceRound(rnd, cparams), balanceRnd)
require.Equal(t, BalanceRound(rnd, cparams), balanceRnd)
return keyManager.VotingKeys(votingRound, balanceRnd)
}
pb.loadRoundParticipationKeys(basics.Round(rnd))
Expand Down
7 changes: 5 additions & 2 deletions agreement/selector.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,10 @@ func (sel selector) CommitteeSize(proto config.ConsensusParams) uint64 {
return sel.Step.committeeSize(proto)
}

func balanceRound(r basics.Round, cparams config.ConsensusParams) basics.Round {
// BalanceRound return the round that should be considered by agreement when
// looking at online stake (and status and key material). It is exported so that
// AVM can provide opcodes that return the same data.
func BalanceRound(r basics.Round, cparams config.ConsensusParams) basics.Round {
return r.SubSaturate(basics.Round(2 * cparams.SeedRefreshInterval * cparams.SeedLookback))
}

Expand All @@ -61,7 +64,7 @@ func membership(l LedgerReader, addr basics.Address, r basics.Round, p period, s
if err != nil {
return
}
balanceRound := balanceRound(r, cparams)
balanceRound := BalanceRound(r, cparams)
seedRound := seedRound(r, cparams)

record, err := l.LookupAgreement(balanceRound, addr)
Expand Down
24 changes: 24 additions & 0 deletions cmd/tealdbg/localLedger.go
Original file line number Diff line number Diff line change
Expand Up @@ -336,6 +336,30 @@ func (l *localLedger) LookupWithoutRewards(rnd basics.Round, addr basics.Address
return ledgercore.ToAccountData(ad), rnd, nil
}

func (l *localLedger) LookupAgreement(rnd basics.Round, addr basics.Address) (basics.OnlineAccountData, error) {
// tealdbg does not understand rewards, so no pending rewards are applied.
// Further, it has no history, so we return the _current_ information,
// ignoring the `rnd` argument.
ad := l.balances[addr]
jannotti marked this conversation as resolved.
Show resolved Hide resolved
return basics.OnlineAccountData{
MicroAlgosWithRewards: ad.MicroAlgos,
VotingData: basics.VotingData{
VoteID: ad.VoteID,
SelectionID: ad.SelectionID,
StateProofID: ad.StateProofID,
VoteFirstValid: ad.VoteFirstValid,
VoteLastValid: ad.VoteLastValid,
VoteKeyDilution: ad.VoteKeyDilution,
},
IncentiveEligible: ad.IncentiveEligible,
}, nil
}

func (l *localLedger) OnlineCirculation(rnd basics.Round, voteRound basics.Round) (basics.MicroAlgos, error) {
// A constant is fine for tealdbg
return basics.Algos(1_000_000_000), nil // 1B
}

func (l *localLedger) GetCreatorForRound(rnd basics.Round, cidx basics.CreatableIndex, ctype basics.CreatableType) (basics.Address, bool, error) {
switch ctype {
case basics.AssetCreatable:
Expand Down
26 changes: 26 additions & 0 deletions daemon/algod/api/server/v2/dryrun.go
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,32 @@ func (dl *dryrunLedger) LookupWithoutRewards(rnd basics.Round, addr basics.Addre
return ledgercore.ToAccountData(ad), rnd, nil
}

func (dl *dryrunLedger) LookupAgreement(rnd basics.Round, addr basics.Address) (basics.OnlineAccountData, error) {
// dryrun does not understand rewards, so we build the result without adding pending rewards.
// we also have no history, so we return current values
ad, _, err := dl.lookup(rnd, addr)
if err != nil {
jannotti marked this conversation as resolved.
Show resolved Hide resolved
return basics.OnlineAccountData{}, err
}
return basics.OnlineAccountData{
MicroAlgosWithRewards: ad.MicroAlgos,
VotingData: basics.VotingData{
VoteID: ad.VoteID,
SelectionID: ad.SelectionID,
StateProofID: ad.StateProofID,
VoteFirstValid: ad.VoteFirstValid,
VoteLastValid: ad.VoteLastValid,
VoteKeyDilution: ad.VoteKeyDilution,
},
IncentiveEligible: ad.IncentiveEligible,
}, nil
}

func (dl *dryrunLedger) OnlineCirculation(rnd basics.Round, voteRnd basics.Round) (basics.MicroAlgos, error) {
// dryrun doesn't support setting the global online stake, so we'll just return a constant
return basics.Algos(1_000_000_000), nil // 1B
}

func (dl *dryrunLedger) LookupApplication(rnd basics.Round, addr basics.Address, aidx basics.AppIndex) (ledgercore.AppResource, error) {
ad, _, err := dl.lookup(rnd, addr)
if err != nil {
Expand Down
11 changes: 9 additions & 2 deletions data/transactions/logic/assembler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -427,6 +427,11 @@ match_label1:
pushbytess "1" "2" "1"
`

const incentiveNonsense = `
online_stake
voter_params_get VoterIncentiveEligible
`

const stateProofNonsense = `
pushbytes 0x0123456789abcd
sumhash512
Expand All @@ -445,7 +450,7 @@ const spliceNonsence = `

const v10Nonsense = v9Nonsense + pairingNonsense + spliceNonsence

const v11Nonsense = v10Nonsense + stateProofNonsense
const v11Nonsense = v10Nonsense + incentiveNonsense + stateProofNonsense

const v6Compiled = "2004010002b7a60c26050242420c68656c6c6f20776f726c6421070123456789abcd208dae2087fbba51304eb02b91f656948397a7946390e8cb70fc9ea4d95f92251d047465737400320032013202320380021234292929292b0431003101310231043105310731083109310a310b310c310d310e310f3111311231133114311533000033000133000233000433000533000733000833000933000a33000b33000c33000d33000e33000f3300113300123300133300143300152d2e01022581f8acd19181cf959a1281f8acd19181cf951a81f8acd19181cf1581f8acd191810f082209240a220b230c240d250e230f2310231123122313231418191a1b1c28171615400003290349483403350222231d4a484848482b50512a632223524100034200004322602261222704634848222862482864286548482228246628226723286828692322700048482371004848361c0037001a0031183119311b311d311e311f312023221e312131223123312431253126312731283129312a312b312c312d312e312f447825225314225427042455220824564c4d4b0222382124391c0081e80780046a6f686e2281d00f23241f880003420001892224902291922494249593a0a1a2a3a4a5a6a7a8a9aaabacadae24af3a00003b003c003d816472064e014f012a57000823810858235b235a2359b03139330039b1b200b322c01a23c1001a2323c21a23c3233e233f8120af06002a494905002a49490700b400b53a03b6b7043cb8033a0c2349c42a9631007300810881088120978101c53a8101c6003a"

Expand All @@ -467,9 +472,11 @@ const spliceCompiled = "d2d3"

const v10Compiled = v9Compiled + pairingCompiled + spliceCompiled

const incentiveCompiled = "757401"

const stateProofCompiled = "80070123456789abcd86494985"

const V11Compiled = v10Compiled + stateProofCompiled
const V11Compiled = v10Compiled + incentiveCompiled + stateProofCompiled

var nonsense = map[uint64]string{
1: v1Nonsense,
Expand Down
4 changes: 3 additions & 1 deletion data/transactions/logic/doc.go
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,8 @@ var opDescByName = map[string]OpDesc{
"asset_params_get": {"X is field F from asset A. Y is 1 if A exists, else 0", "params: Txn.ForeignAssets offset (or, since v4, an _available_ asset id. Return: did_exist flag (1 if the asset existed and 0 otherwise), value.", []string{"asset params field index"}},
"app_params_get": {"X is field F from app A. Y is 1 if A exists, else 0", "params: Txn.ForeignApps offset or an _available_ app id. Return: did_exist flag (1 if the application existed and 0 otherwise), value.", []string{"app params field index"}},
"acct_params_get": {"X is field F from account A. Y is 1 if A owns positive algos, else 0", "", []string{"account params field index"}},
"voter_params_get": {"X is field F from online account A. Y is 1 if A had positive algos online in the agreement round, else 0", "", []string{"voter params field index"}},
"online_stake": {"the total online stake in the agreement round", "", nil},
"assert": {"immediately fail unless A is a non-zero number", "", nil},
"callsub": {"branch unconditionally to TARGET, saving the next instruction on the call stack", "The call stack is separate from the data stack. Only `callsub`, `retsub`, and `proto` manipulate it.", []string{"branch offset"}},
"proto": {"Prepare top call frame for a retsub that will assume A args and R return values.", "Fails unless the last instruction executed was a `callsub`.", []string{"number of arguments", "number of return values"}},
Expand Down Expand Up @@ -355,7 +357,7 @@ var OpGroups = map[string][]string{
"Cryptography": {"sha256", "keccak256", "sha512_256", "sha3_256", "sumhash512", "falcon_verify", "ed25519verify", "ed25519verify_bare", "ecdsa_verify", "ecdsa_pk_recover", "ecdsa_pk_decompress", "vrf_verify", "ec_add", "ec_scalar_mul", "ec_pairing_check", "ec_multi_scalar_mul", "ec_subgroup_check", "ec_map_to"},
"Loading Values": {"intcblock", "intc", "intc_0", "intc_1", "intc_2", "intc_3", "pushint", "pushints", "bytecblock", "bytec", "bytec_0", "bytec_1", "bytec_2", "bytec_3", "pushbytes", "pushbytess", "bzero", "arg", "arg_0", "arg_1", "arg_2", "arg_3", "args", "txn", "gtxn", "txna", "txnas", "gtxna", "gtxnas", "gtxns", "gtxnsa", "gtxnsas", "global", "load", "loads", "store", "stores", "gload", "gloads", "gloadss", "gaid", "gaids"},
"Flow Control": {"err", "bnz", "bz", "b", "return", "pop", "popn", "dup", "dup2", "dupn", "dig", "bury", "cover", "uncover", "frame_dig", "frame_bury", "swap", "select", "assert", "callsub", "proto", "retsub", "switch", "match"},
"State Access": {"balance", "min_balance", "app_opted_in", "app_local_get", "app_local_get_ex", "app_global_get", "app_global_get_ex", "app_local_put", "app_global_put", "app_local_del", "app_global_del", "asset_holding_get", "asset_params_get", "app_params_get", "acct_params_get", "log", "block"},
"State Access": {"balance", "min_balance", "app_opted_in", "app_local_get", "app_local_get_ex", "app_global_get", "app_global_get_ex", "app_local_put", "app_global_put", "app_local_del", "app_global_del", "asset_holding_get", "asset_params_get", "app_params_get", "acct_params_get", "voter_params_get", "online_stake", "log", "block"},
"Box Access": {"box_create", "box_extract", "box_replace", "box_splice", "box_del", "box_len", "box_get", "box_put", "box_resize"},
"Inner Transactions": {"itxn_begin", "itxn_next", "itxn_field", "itxn_submit", "itxn", "itxna", "itxnas", "gitxn", "gitxna", "gitxnas"},
}
Expand Down
57 changes: 56 additions & 1 deletion data/transactions/logic/eval.go
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,11 @@ type LedgerForLogic interface {
Round() basics.Round
PrevTimestamp() int64

// These are simplifications of the underlying Ledger methods that take a
// round argument. They implicitly use agreement's BalanceRound (320 back).
AgreementData(addr basics.Address) (basics.OnlineAccountData, error)
OnlineStake() (basics.MicroAlgos, error)

AssetHolding(addr basics.Address, assetIdx basics.AssetIndex) (basics.AssetHolding, error)
AssetParams(aidx basics.AssetIndex) (basics.AssetParams, basics.Address, error)
AppParams(aidx basics.AppIndex) (basics.AppParams, basics.Address, error)
Expand Down Expand Up @@ -3736,7 +3741,7 @@ func (cx *EvalContext) globalFieldToValue(fs globalFieldSpec) (sv stackValue, er
return sv, fmt.Errorf("invalid global field %s", fs.field)
}

if fs.ftype.AVMType != sv.avmType() {
if err == nil && fs.ftype.AVMType != sv.avmType() {
return sv, fmt.Errorf("%s expected field type is %s but got %s", fs.field, fs.ftype, sv.avmType())
}

Expand Down Expand Up @@ -5019,12 +5024,62 @@ func opAcctParamsGet(cx *EvalContext) error {
value.Uint = account.TotalBoxes
case AcctTotalBoxBytes:
value.Uint = account.TotalBoxBytes
case AcctIncentiveEligible:
value = boolToSV(account.IncentiveEligible)
case AcctLastHeartbeat:
value.Uint = uint64(account.LastHeartbeat)
case AcctLastProposed:
value.Uint = uint64(account.LastProposed)
default:
return fmt.Errorf("invalid account field %s", fs.field)
}
cx.Stack[last] = value
cx.Stack = append(cx.Stack, boolToSV(account.MicroAlgos.Raw > 0))
return nil
}

func opVoterParamsGet(cx *EvalContext) error {
last := len(cx.Stack) - 1 // acct
addr, _, err := cx.accountReference(cx.Stack[last])
if err != nil {
return err
}

paramField := VoterParamsField(cx.program[cx.pc+1])
fs, ok := voterParamsFieldSpecByField(paramField)
if !ok || fs.version > cx.version {
return fmt.Errorf("invalid voter_params_get field %d", paramField)
}

account, err := cx.Ledger.AgreementData(addr)
if err != nil {
return err
}

var value stackValue

switch fs.field {
case VoterBalance:
value.Uint = account.MicroAlgosWithRewards.Raw
case VoterIncentiveEligible:
value = boolToSV(account.IncentiveEligible)
default:
return fmt.Errorf("invalid voter field %s", fs.field)
}
cx.Stack[last] = value
cx.Stack = append(cx.Stack, boolToSV(account.MicroAlgosWithRewards.Raw > 0))
return nil
}

func opOnlineStake(cx *EvalContext) error {
amount, err := cx.Ledger.OnlineStake()
if err != nil {
return err
}
cx.Stack = append(cx.Stack, stackValue{Uint: amount.Raw})
return nil
}

func opLog(cx *EvalContext) error {
last := len(cx.Stack) - 1

Expand Down
54 changes: 54 additions & 0 deletions data/transactions/logic/evalStateful_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,8 @@ log
"int 0; int 0; app_params_get AppApprovalProgram": 5,
"byte 0x01; log": 5,
sender + "acct_params_get AcctBalance": 7,
sender + "voter_params_get VoterBalance": 11,
"online_stake": 11,

"byte 0x1234; int 12; box_create": 8,
"byte 0x1234; int 12; int 4; box_extract": 8,
Expand Down Expand Up @@ -487,6 +489,9 @@ func testApp(t *testing.T, program string, ep *EvalParams, problems ...string) (
return testAppBytes(t, ops.Program, ep, problems...)
}

// testAppCreator is the creator of the 888 app that is inserted when testing an app call
const testAppCreator = "47YPQTIGQEO7T4Y4RWDYWEKV6RTR2UNBQXBABEEGM72ESWDQNCQ52OPASU"

func testAppBytes(t *testing.T, program []byte, ep *EvalParams, problems ...string) (transactions.EvalDelta, error) {
t.Helper()
if ep == nil {
Expand All @@ -497,6 +502,12 @@ func testAppBytes(t *testing.T, program []byte, ep *EvalParams, problems ...stri
aid := ep.TxnGroup[0].Txn.ApplicationID
if aid == 0 {
aid = basics.AppIndex(888)
// we're testing an app call without the caller specifying details about
// the app, so conjure up buring app params to make the `global
// AppCreator` work.
addr, err := basics.UnmarshalChecksumAddress(testAppCreator)
require.NoError(t, err)
ep.Ledger.(*Ledger).NewApp(addr, 888, basics.AppParams{})
}
return testAppFull(t, program, 0, aid, ep, problems...)
}
Expand Down Expand Up @@ -1598,6 +1609,49 @@ func TestAcctParams(t *testing.T) {
ledger.NewAsset(tx.Sender, 3000, basics.AssetParams{})
test("txn Sender; acct_params_get AcctTotalAssetsCreated; assert; int 1; ==")
test("txn Sender; acct_params_get AcctTotalAssets; assert; int 1; ==")

if ep.Proto.LogicSigVersion < 11 {
return // the rest uses fields that came at 11
}
test("txn Sender; acct_params_get AcctIncentiveEligible; assert; !")
test("txn Sender; acct_params_get AcctLastHeartbeat; assert; !")
test("txn Sender; acct_params_get AcctLastProposed; assert; !")
})
}

func TestVoterParams(t *testing.T) {
partitiontest.PartitionTest(t)
t.Parallel()

// start at 11 for acct_params_get
testLogicRange(t, 11, 0, func(t *testing.T, ep *EvalParams, tx *transactions.Transaction, ledger *Ledger) {
test := func(source string) {
t.Helper()
testApp(t, source, ep)
}

test("txn Sender; voter_params_get VoterBalance; !; assert; int 0; ==")
test("txn Sender; voter_params_get VoterIncentiveEligible; !; assert; int 0; ==")

// The logic package test ledger just returns current values
ledger.NewAccount(tx.Sender, 42)
test("txn Sender; voter_params_get VoterBalance; assert; int 42; ==")
test("txn Sender; voter_params_get VoterIncentiveEligible; assert; !")
})
}

func TestOnlineStake(t *testing.T) {
partitiontest.PartitionTest(t)
t.Parallel()

// start at 11 for online_stake
testLogicRange(t, 11, 0, func(t *testing.T, ep *EvalParams, tx *transactions.Transaction, ledger *Ledger) {
test := func(source string) {
t.Helper()
testApp(t, source, ep)
}

test("online_stake; int 3333000000; ==") // test ledger hard codes 3333 algos
})
}

Expand Down
13 changes: 3 additions & 10 deletions data/transactions/logic/eval_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1160,8 +1160,6 @@ int 1
&&
`

const testAddr = "47YPQTIGQEO7T4Y4RWDYWEKV6RTR2UNBQXBABEEGM72ESWDQNCQ52OPASU"

const globalV2TestProgram = globalV1TestProgram + `
global LogicSigVersion
int 1
Expand All @@ -1182,7 +1180,7 @@ int 888
`
const globalV3TestProgram = globalV2TestProgram + `
global CreatorAddress
addr ` + testAddr + `
addr ` + testAppCreator + `
==
&&
`
Expand Down Expand Up @@ -1239,10 +1237,10 @@ const globalV11TestProgram = globalV10TestProgram + `
// No new globals in v11
`

func TestGlobal(t *testing.T) {
func TestAllGlobals(t *testing.T) {
partitiontest.PartitionTest(t)

t.Parallel()

type desc struct {
lastField GlobalField
program string
Expand Down Expand Up @@ -1270,10 +1268,6 @@ func TestGlobal(t *testing.T) {
require.Equal(t, tests[AssemblerMaxVersion].lastField, invalidGlobalField-1,
"did you add a new global field?")

ledger := NewLedger(nil)
addr, err := basics.UnmarshalChecksumAddress(testAddr)
require.NoError(t, err)
ledger.NewApp(addr, 888, basics.AppParams{})
for v := uint64(1); v <= AssemblerMaxVersion; v++ {
_, ok := tests[v]
require.True(t, ok)
Expand All @@ -1294,7 +1288,6 @@ func TestGlobal(t *testing.T) {
appcall.Txn.Group = crypto.Digest{0x07, 0x06}

ep := defaultAppParams(appcall)
ep.Ledger = ledger
testApp(t, tests[v].program, ep)
})
}
Expand Down
Loading
Loading