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 incentives #20

Closed
wants to merge 7 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
16 changes: 0 additions & 16 deletions cmd/algokey/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ import (

"github.com/algorand/go-algorand/crypto"
"github.com/algorand/go-algorand/crypto/passphrase"
"github.com/muesli/termenv"
)

const (
Expand Down Expand Up @@ -123,18 +122,3 @@ func readFile(filename string) ([]byte, error) {
}
return os.ReadFile(filename)
}

// printDiscreetly Print a secret string to an alternate screen,
// so the string isn't printed to the terminal.
func printDiscreetly(w io.Writer, promptMsg, secretMsg string) error {
output := termenv.NewOutput(w)
output.AltScreen()
defer output.ExitAltScreen()
if _, err := fmt.Fprintf(output, "%s\n\n%s\n\nPress 'Enter' key to continue.", promptMsg, secretMsg); err != nil {
return err
}
if _, err := fmt.Scanln(); err != nil {
return err
}
return nil
}
39 changes: 0 additions & 39 deletions cmd/algokey/common_test.go

This file was deleted.

12 changes: 1 addition & 11 deletions cmd/algokey/generate.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ package main

import (
"fmt"
"os"

"github.com/spf13/cobra"

Expand All @@ -28,12 +27,10 @@ import (

var generateKeyfile string
var generatePubkeyfile string
var generateDiscreet bool

func init() {
generateCmd.Flags().StringVarP(&generateKeyfile, "keyfile", "f", "", "Private key filename")
generateCmd.Flags().StringVarP(&generatePubkeyfile, "pubkeyfile", "p", "", "Public key filename")
generateCmd.Flags().BoolVar(&generateDiscreet, "discreet", false, "Print mnemonic discreetly to an alternate screen")
}

var generateCmd = &cobra.Command{
Expand All @@ -49,14 +46,7 @@ var generateCmd = &cobra.Command{
key := crypto.GenerateSignatureSecrets(seed)
publicKeyChecksummed := basics.Address(key.SignatureVerifier).String()

if generateDiscreet {
if err := printDiscreetly(os.Stderr, "**Important** write this private key mnemonic phrase in a safe place. Do not share it to anyone", fmt.Sprintf("Private key mnemonic: %s", mnemonic)); err != nil {
fmt.Fprintf(os.Stderr, "Fail to print mnemonic: %v", err)
os.Exit(1)
}
} else {
fmt.Printf("Private key mnemonic: %s\n", mnemonic)
}
fmt.Printf("Private key mnemonic: %s\n", mnemonic)
fmt.Printf("Public key: %s\n", publicKeyChecksummed)

if generateKeyfile != "" {
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]
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
3 changes: 2 additions & 1 deletion config/localTemplate.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import (
"time"

"github.com/algorand/go-algorand/protocol"
"github.com/algorand/go-algorand/util"
"github.com/algorand/go-algorand/util/codecs"
)

Expand Down Expand Up @@ -893,7 +894,7 @@ func moveDirIfExists(logger logger, srcdir, dstdir string, files ...string) erro
// then, check if any files exist in srcdir, and move them to dstdir
for _, file := range files {
if _, err := os.Stat(filepath.Join(srcdir, file)); err == nil {
if err := os.Rename(filepath.Join(srcdir, file), filepath.Join(dstdir, file)); err != nil {
if err := util.MoveFile(filepath.Join(srcdir, file), filepath.Join(dstdir, file)); err != nil {
return fmt.Errorf("failed to move file %s from %s to %s: %v", file, srcdir, dstdir, err)
}
logger.Infof("Moved DB file %s from ColdDataDir %s to HotDataDir %s", file, srcdir, dstdir)
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 {
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
Loading
Loading