From 4039875e8ff3a301f3cab41476906ffb915fe434 Mon Sep 17 00:00:00 2001 From: John Jannotti Date: Thu, 19 Dec 2024 09:43:33 -0800 Subject: [PATCH 1/4] Changes for block incentives and v11 opcodes --- dev/TEAL.md | 34 +++++---- dev/TEAL_opcodes.md | 108 ++++++++++++++++++++------ dev/ledger.md | 179 ++++++++++++++++++++++++++++++++++++-------- 3 files changed, 254 insertions(+), 67 deletions(-) diff --git a/dev/TEAL.md b/dev/TEAL.md index 4b62396..3aa813d 100644 --- a/dev/TEAL.md +++ b/dev/TEAL.md @@ -60,9 +60,6 @@ assembly time to do type checking and to provide more informative error messages | Name | Bound | AVM Type | | ---- | ---- | -------- | -| [32]byte | len(x) == 32 | []byte | -| [64]byte | len(x) == 64 | []byte | -| [80]byte | len(x) == 80 | []byte | | []byte | len(x) <= 4096 | []byte | | address | len(x) == 32 | []byte | | any | | any | @@ -148,18 +145,14 @@ of a contract account. transaction against the contract account is for the program to approve it. -The size of a Smart Signature is defined as the length of its bytecode -plus the length of all its Args. The sum of the sizes of all Smart -Signatures in a group must not exceed 1000 bytes times the number of -transactions in the group (1000 bytes is defined in consensus parameter -`LogicSigMaxSize`). - -Each opcode has an associated cost, usually 1, but a few slow operations -have higher costs. Prior to v4, the program's cost was estimated as the -static sum of all the opcode costs in the program (whether they were -actually executed or not). Beginning with v4, the program's cost is -tracked dynamically, while being evaluated. If the program exceeds its -budget, it fails. +The bytecode plus the length of all Args must add up to no more than +1000 bytes (consensus parameter LogicSigMaxSize). Each opcode has an +associated cost, usually 1, but a few slow operations have higher +costs. Prior to v4, the program's cost was estimated as the static sum +of all the opcode costs in the program (whether they were actually +executed or not). Beginning with v4, the program's cost is tracked +dynamically, while being evaluated. If the program exceeds its budget, +it fails. The total program cost of all Smart Signatures in a group must not exceed 20,000 (consensus parameter LogicSigMaxCost) times the number @@ -490,6 +483,7 @@ these results may contain leading zero bytes. | `ec_multi_scalar_mul g` | for curve points A and scalars B, return curve point B0A0 + B1A1 + B2A2 + ... + BnAn | | `ec_subgroup_check g` | 1 if A is in the main prime-order subgroup of G (including the point at infinity) else 0. Program fails if A is not in G at all. | | `ec_map_to g` | maps field element A to group G | +| `mimc c` | MiMC hash of scalars A, using curve and parameters specified by configuration C | ### Loading Values @@ -646,6 +640,11 @@ Global fields are fields that are common to all the transactions in the group. I | 15 | AssetCreateMinBalance | uint64 | v10 | The additional minimum balance required to create (and opt-in to) an asset. | | 16 | AssetOptInMinBalance | uint64 | v10 | The additional minimum balance required to opt-in to an asset. | | 17 | GenesisHash | [32]byte | v10 | The Genesis Hash for the network. | +| 18 | PayoutsEnabled | bool | v11 | Whether block proposal payouts are enabled. | +| 19 | PayoutsGoOnlineFee | uint64 | v11 | The fee required in a keyreg transaction to make an account incentive eligible. | +| 20 | PayoutsPercent | uint64 | v11 | The percentage of transaction fees in a block that can be paid to the block proposer. | +| 21 | PayoutsMinBalance | uint64 | v11 | The minimum algo balance an account must have in the agreement round to receive block payouts in the proposal round. | +| 22 | PayoutsMaxBalance | uint64 | v11 | The maximum algo balance an account can have in the agreement round to receive block payouts in the proposal round. | **Asset Fields** @@ -709,6 +708,9 @@ Account fields used in the `acct_params_get` opcode. | 9 | AcctTotalAssets | uint64 | v8 | The numbers of ASAs held by this account (including ASAs this account created). | | 10 | AcctTotalBoxes | uint64 | v8 | The number of existing boxes created by this account's app. | | 11 | AcctTotalBoxBytes | uint64 | v8 | The total number of bytes used by this account's app's box keys and values. | +| 12 | AcctIncentiveEligible | bool | v11 | Has this account opted into block payouts | +| 13 | AcctLastProposed | uint64 | v11 | The round number of the last block this account proposed. | +| 14 | AcctLastHeartbeat | uint64 | v11 | The round number of the last block this account sent a heartbeat. | ### Flow Control @@ -759,6 +761,8 @@ Account fields used in the `acct_params_get` opcode. | `asset_params_get f` | X is field F from asset A. Y is 1 if A exists, else 0 | | `app_params_get f` | X is field F from app A. Y is 1 if A exists, else 0 | | `acct_params_get f` | X is field F from account A. Y is 1 if A owns positive algos, else 0 | +| `voter_params_get f` | X is field F from online account A as of the balance round: 320 rounds before the current round. Y is 1 if A had positive algos online in the agreement round, else Y is 0 and X is a type specific zero-value | +| `online_stake` | the total online stake in the agreement round | | `log` | write A to log state of the current application | | `block f` | field F of block A. Fail unless A falls between txn.LastValid-1002 and txn.FirstValid (exclusive) | diff --git a/dev/TEAL_opcodes.md b/dev/TEAL_opcodes.md index bbb6e50..a968f26 100644 --- a/dev/TEAL_opcodes.md +++ b/dev/TEAL_opcodes.md @@ -6,7 +6,7 @@ abstract: > Algorand allows transactions to be effectively signed by a small program. If the program evaluates to true then the transaction is allowed. This document defines the language opcodes and byte encoding. --- -# v10 Opcodes +# v11 Opcodes Ops have a 'cost' of 1 unless otherwise specified. @@ -51,7 +51,7 @@ The 32 byte public key is the last element on the stack, preceded by the 64 byte - Syntax: `ecdsa_verify V` where V: [ECDSA](#field-group-ecdsa) - Bytecode: 0x05 {uint8} -- Stack: ..., A: [32]byte, B: []byte, C: []byte, D: []byte, E: []byte → ..., bool +- Stack: ..., A: [32]byte, B: [32]byte, C: [32]byte, D: [32]byte, E: [32]byte → ..., bool - for (data A, signature B, C and pubkey D, E) verify the signature of the data against the pubkey => {0 or 1} - **Cost**: Secp256k1=1700; Secp256r1=2500 - Availability: v5 @@ -72,7 +72,7 @@ The 32 byte Y-component of a public key is the last element on the stack, preced - Syntax: `ecdsa_pk_decompress V` where V: [ECDSA](#field-group-ecdsa) - Bytecode: 0x06 {uint8} -- Stack: ..., A: []byte → ..., X: []byte, Y: []byte +- Stack: ..., A: [33]byte → ..., X: [32]byte, Y: [32]byte - decompress pubkey A into components X, Y - **Cost**: Secp256k1=650; Secp256r1=2400 - Availability: v5 @@ -83,7 +83,7 @@ The 33 byte public key in a compressed form to be decompressed into X and Y (top - Syntax: `ecdsa_pk_recover V` where V: [ECDSA](#field-group-ecdsa) - Bytecode: 0x07 {uint8} -- Stack: ..., A: [32]byte, B: uint64, C: [32]byte, D: [32]byte → ..., X: []byte, Y: []byte +- Stack: ..., A: [32]byte, B: uint64, C: [32]byte, D: [32]byte → ..., X: [32]byte, Y: [32]byte - for (data A, recovery id B, signature C, D) recover a public key - **Cost**: 2000 - Availability: v5 @@ -183,7 +183,7 @@ Overflow is an error condition which halts execution and fails the transaction. ## itob - Bytecode: 0x16 -- Stack: ..., A: uint64 → ..., []byte +- Stack: ..., A: uint64 → ..., [8]byte - converts uint64 A to big-endian byte array, always of length 8 ## btoi @@ -470,6 +470,11 @@ Fields | 15 | AssetCreateMinBalance | uint64 | v10 | The additional minimum balance required to create (and opt-in to) an asset. | | 16 | AssetOptInMinBalance | uint64 | v10 | The additional minimum balance required to opt-in to an asset. | | 17 | GenesisHash | [32]byte | v10 | The Genesis Hash for the network. | +| 18 | PayoutsEnabled | bool | v11 | Whether block proposal payouts are enabled. | +| 19 | PayoutsGoOnlineFee | uint64 | v11 | The fee required in a keyreg transaction to make an account incentive eligible. | +| 20 | PayoutsPercent | uint64 | v11 | The percentage of transaction fees in a block that can be paid to the block proposer. | +| 21 | PayoutsMinBalance | uint64 | v11 | The minimum algo balance an account must have in the agreement round to receive block payouts in the proposal round. | +| 22 | PayoutsMaxBalance | uint64 | v11 | The maximum algo balance an account can have in the agreement round to receive block payouts in the proposal round. | ## gtxn @@ -904,7 +909,7 @@ params: Txn.Accounts offset (or, since v4, an _available_ account address), _ava ## app_local_get - Bytecode: 0x62 -- Stack: ..., A, B: []byte → ..., any +- Stack: ..., A, B: stateKey → ..., any - local state of the key B in the current application in account A - Availability: v2 - Mode: Application @@ -914,7 +919,7 @@ params: Txn.Accounts offset (or, since v4, an _available_ account address), stat ## app_local_get_ex - Bytecode: 0x63 -- Stack: ..., A, B: uint64, C: []byte → ..., X: any, Y: bool +- Stack: ..., A, B: uint64, C: stateKey → ..., X: any, Y: bool - X is the local state of application B, key C in account A. Y is 1 if key existed, else 0 - Availability: v2 - Mode: Application @@ -924,7 +929,7 @@ params: Txn.Accounts offset (or, since v4, an _available_ account address), _ava ## app_global_get - Bytecode: 0x64 -- Stack: ..., A: []byte → ..., any +- Stack: ..., A: stateKey → ..., any - global state of the key A in the current application - Availability: v2 - Mode: Application @@ -934,7 +939,7 @@ params: state key. Return: value. The value is zero (of type uint64) if the key ## app_global_get_ex - Bytecode: 0x65 -- Stack: ..., A: uint64, B: []byte → ..., X: any, Y: bool +- Stack: ..., A: uint64, B: stateKey → ..., X: any, Y: bool - X is the global state of application A, key B. Y is 1 if key existed, else 0 - Availability: v2 - Mode: Application @@ -944,7 +949,7 @@ params: Txn.ForeignApps offset (or, since v4, an _available_ application id), st ## app_local_put - Bytecode: 0x66 -- Stack: ..., A, B: []byte, C → ... +- Stack: ..., A, B: stateKey, C → ... - write C to key B in account A's local state of the current application - Availability: v2 - Mode: Application @@ -954,7 +959,7 @@ params: Txn.Accounts offset (or, since v4, an _available_ account address), stat ## app_global_put - Bytecode: 0x67 -- Stack: ..., A: []byte, B → ... +- Stack: ..., A: stateKey, B → ... - write B to key A in the global state of the current application - Availability: v2 - Mode: Application @@ -962,7 +967,7 @@ params: Txn.Accounts offset (or, since v4, an _available_ account address), stat ## app_local_del - Bytecode: 0x68 -- Stack: ..., A, B: []byte → ... +- Stack: ..., A, B: stateKey → ... - delete key B from account A's local state of the current application - Availability: v2 - Mode: Application @@ -974,7 +979,7 @@ Deleting a key which is already absent has no effect on the application local st ## app_global_del - Bytecode: 0x69 -- Stack: ..., A: []byte → ... +- Stack: ..., A: stateKey → ... - delete key A from the global state of the current application - Availability: v2 - Mode: Application @@ -1090,7 +1095,37 @@ Fields | 9 | AcctTotalAssets | uint64 | v8 | The numbers of ASAs held by this account (including ASAs this account created). | | 10 | AcctTotalBoxes | uint64 | v8 | The number of existing boxes created by this account's app. | | 11 | AcctTotalBoxBytes | uint64 | v8 | The total number of bytes used by this account's app's box keys and values. | +| 12 | AcctIncentiveEligible | bool | v11 | Has this account opted into block payouts | +| 13 | AcctLastProposed | uint64 | v11 | The round number of the last block this account proposed. | +| 14 | AcctLastHeartbeat | uint64 | v11 | The round number of the last block this account sent a heartbeat. | + + +## voter_params_get + +- Syntax: `voter_params_get F` where F: [voter_params](#field-group-voter_params) +- Bytecode: 0x74 {uint8} +- Stack: ..., A → ..., X: any, Y: bool +- X is field F from online account A as of the balance round: 320 rounds before the current round. Y is 1 if A had positive algos online in the agreement round, else Y is 0 and X is a type specific zero-value +- Availability: v11 +- Mode: Application +### voter_params + +Fields + +| Index | Name | Type | In | Notes | +| - | ------ | -- | - | --------- | +| 0 | VoterBalance | uint64 | v6 | Online stake in microalgos | +| 1 | VoterIncentiveEligible | bool | | Had this account opted into block payouts | + + +## online_stake + +- Bytecode: 0x75 +- Stack: ... → ..., uint64 +- the total online stake in the agreement round +- Availability: v11 +- Mode: Application ## min_balance @@ -1262,7 +1297,7 @@ bitlen interprets arrays as big-endian integers, unlike setbit/getbit ## bsqrt - Bytecode: 0x96 -- Stack: ..., A: []byte → ..., []byte +- Stack: ..., A: bigint → ..., bigint - The largest integer I such that I^2 <= A. A and I are interpreted as big-endian unsigned integers - **Cost**: 40 - Availability: v6 @@ -1279,7 +1314,7 @@ The notation A,B indicates that A and B are interpreted as a uint128 value, with ## sha3_256 - Bytecode: 0x98 -- Stack: ..., A: []byte → ..., []byte +- Stack: ..., A: []byte → ..., [32]byte - SHA3_256 hash of value A, yields [32]byte - **Cost**: 130 - Availability: v7 @@ -1361,7 +1396,7 @@ The notation A,B indicates that A and B are interpreted as a uint128 value, with ## b% - Bytecode: 0xaa -- Stack: ..., A: []byte, B: []byte → ..., []byte +- Stack: ..., A: bigint, B: bigint → ..., bigint - A modulo B. A and B are interpreted as big-endian unsigned integers. Fail if B is zero. - **Cost**: 20 - Availability: v4 @@ -1616,7 +1651,7 @@ For boxes that exceed 4,096 bytes, consider `box_create`, `box_extract`, and `bo - Syntax: `vrf_verify S` where S: [vrf_verify](#field-group-vrf_verify) - Bytecode: 0xd0 {uint8} -- Stack: ..., A: []byte, B: [80]byte, C: [32]byte → ..., X: []byte, Y: bool +- Stack: ..., A: []byte, B: [80]byte, C: [32]byte → ..., X: [64]byte, Y: bool - Verify the proof B of message A against pubkey C. Returns vrf output and verification flag. - **Cost**: 5700 - Availability: v7 @@ -1644,10 +1679,18 @@ Standards Fields -| Index | Name | Type | Notes | -| - | ------ | -- | --------- | -| 0 | BlkSeed | []byte | | -| 1 | BlkTimestamp | uint64 | | +| Index | Name | Type | In | Notes | +| - | ------ | -- | - | --------- | +| 0 | BlkSeed | [32]byte | | | +| 1 | BlkTimestamp | uint64 | | | +| 2 | BlkProposer | address | v11 | | +| 3 | BlkFeesCollected | uint64 | v11 | | +| 4 | BlkBonus | uint64 | v11 | | +| 5 | BlkBranch | [32]byte | v11 | | +| 6 | BlkFeeSink | address | v11 | | +| 7 | BlkProtocol | []byte | v11 | | +| 8 | BlkTxnCounter | uint64 | v11 | | +| 9 | BlkProposerPayout | uint64 | v11 | | ## box_splice @@ -1754,3 +1797,26 @@ The name `ec_multi_scalar_mul` was chosen to reflect common usage, but a more co BN254 points are mapped by the SVDW map. BLS12-381 points are mapped by the SSWU map. G1 element inputs are base field elements and G2 element inputs are quadratic field elements, with nearly the same encoding rules (for field elements) as defined in `ec_add`. There is one difference of encoding rule: G1 element inputs do not need to be 0-padded if they fit in less than 32 bytes for BN254 and less than 48 bytes for BLS12-381. (As usual, the empty byte array represents 0.) G2 elements inputs need to be always have the required size. + +## mimc + +- Syntax: `mimc C` where C: [Mimc Configurations](#field-group-mimc configurations) +- Bytecode: 0xe6 {uint8} +- Stack: ..., A: []byte → ..., [32]byte +- MiMC hash of scalars A, using curve and parameters specified by configuration C +- **Cost**: BN254Mp110=10 + 550 per 32 bytes of A; BLS12_381Mp111=10 + 550 per 32 bytes of A +- Availability: v11 + +### Mimc Configurations + +Parameters + +| Index | Name | Notes | +| - | ------ | --------- | +| 0 | BN254Mp110 | MiMC configuration for the BN254 curve with Miyaguchi-Preneel mode, 110 rounds, exponent 5, seed "seed" | +| 1 | BLS12_381Mp111 | MiMC configuration for the BLS12-381 curve with Miyaguchi-Preneel mode, 111 rounds, exponent 5, seed "seed" | + + +A is a list of concatenated 32 byte big-endian unsigned integer scalars. Fail if A's length is not a multiple of 32 or any element exceeds the curve modulus. + +The MiMC hash function has known collisions since any input which is a multiple of the elliptic curve modulus will hash to the same value. MiMC is thus not a general purpose hash function, but meant to be used in zero knowledge applications to match a zk-circuit implementation. diff --git a/dev/ledger.md b/dev/ledger.md index dd544a0..4b6a5a8 100644 --- a/dev/ledger.md +++ b/dev/ledger.md @@ -132,18 +132,63 @@ The block header contains the following components: protocol version that supported the transaction counter. The counter is stored in msgpack field `tc`. - - The block's _expired participation accounts_, which contains an optional slice of - public keys of accounts. These accounts are expected to have their participation - key expire by the end of the round (or was expired before the current round). The - msgpack representation of the components are described in detail below. - The slice is stored in msgpack key `partupdrmv`. - -The block's _expired participation accounts_ slice is valid as long as the participation -keys of all the accounts in the slice are expired by the end of the round or were -expired before, the accounts themselves would have been online at the end of the -round if they were not included in the slice, and the number of elements in the slice is -less or equal to 32. A block proposer may not include all such -accounts in the slice and may even omit the slice completely. + - The block's _proposer_, which is the address of the account that + proposed the block. The proposer is stored in msgpack field `prp`. + + - The block's _fees collected_ is the sum of all fees paid by transactions in + the block and is stored in msgpack field `fc`. + + - The potential _bonus incentive_ is the amount, in MicroAlgos, that + may be paid to the proposer of this block beyond the amount + available from fees. It is stored in msgpack field `bi`. It may be + set during a consensus upgrade, or else it must be equal to the + value from the previous block in most rounds, or be 99% of the + previous value (rounded down) if the round of this block is 0 + modulo 1,000,000. + + - The _proposer payout_ is the actual amount that is moved from the + $I_f$ to the proposer, and is stored in msgpack field `pp`. If the + proposer is not eligible, as described below, the _proposer payout_ + must be 0. If the proposer is eligible, the proposer payout is + valid if it is less than or equal to the the current potential + payout, which is computed as the sum of the _bonus incentive_ and + half of the _fees collected_. + + - The block's _expired participation accounts_, which contains an + optional list of account addresses. These accounts' participation + key expire by the end of the current round, with exact rules below. + The list is stored in msgpack key `partupdrmv`. + + - The block's _suspended participation accounts_, which contains an + optional list of account addresses. These accounts are have not + recently demonstrated that they available and participating, with + exact rules below. The list is stored in msgpack key `partupdabs`. + +A proposer is _eligible_ for bonus payouts if the account's +`IncentiveEligible` flag is true _and_ its online balance is between +30,000 Algos and 70 million Algos. + +The _expired participation accounts_ list is valid as long as the +participation keys of all the accounts in the slice are expired by the +end of the round, the accounts themselves would have been online at +the end of the round if they were not included in the list, and the +number of elements in the list is less than or equal to 32. A block +proposer may not include all such accounts in the list and may even +omit the list completely. + +The _suspended participation accounts_ list is valid if, for each +included address, the account is _online_, incentive _eligible_, and +is either _absent_ or _failing a challenge_ as of the current round. +An account is _absent_ if its `LastHeartbeat` and `LastProposed` +rounds are both more than $20n$ rounds before `current`, where $n$ is +the reciprocal of the account's fraction of online stake. An account +is _failing a challenge_ if the first five bits of the account's +address matches the first five bits of an active challenge round's +block seed, and the active challenge round is between 200 and 400 +rounds before the current round. An active challenge round is a round +that is 0 modulo 1000. The length of the list must not exceed 32. A +block proposer may not include all such accounts in the list and may +even omit the list completely. The block body is the block's transaction sequence, which describes the sequence of updates (transactions) to the account state and box state. @@ -295,11 +340,15 @@ A valid block's reward state matches the expected reward state. \newcommand \Record {\mathrm{Record}} \newcommand \pk {\mathrm{pk}} +\newcommand \ie {\mathrm{ie}} -The _balances_ are a set of mappings from _addresses_, 256-bit integers, to -_balance records_. A _balance record_ contains the following fields: the -account _raw balance_, the account _status_, the account _rewards base_ and -_total awarded amount_, the account _spending key_, and the account [_participation keys_][partkey-spec]. +The _balances_ are a set of mappings from _addresses_, 256-bit +integers, to _balance records_. A _balance record_ contains the +following fields: the account _raw balance_, the account _status_, the +block incentive _eligibility_ flag, the account _last_proposed_ round, the +account _last_heartbeat_ round, the account _rewards base_ and _total +awarded amount_, the account _spending key_, and the account +[_participation keys_][partkey-spec]. The account raw balance $a_I$ is a 64-bit unsigned integer which determines how much money the address has. @@ -340,6 +389,10 @@ Transactions from this account must have this value (or, if this value zero, the The account's participation keys $\pk$ are defined in Algorand's [specification of participation keys][partkey-spec]. +The account's eligibility $\ie$ is a flag that determines whether the +account has elected to receive payouts for proposing blocks (assuming +it meets balance requirements at the time of proposal). + An account's participation keys and voting stake from a recent round is returned by the $\Record$ procedure in the [Byzantine Agreement Protocol][abft-spec]. @@ -540,11 +593,22 @@ any asset cannot be closed. # Participation Updates -Participation updates contains a single list of addresses of accounts which -have been deemed to be _expired_. An account is said to be expired when the last -valid vote round in its participation key is strictly less than the current round -that is being processed. Once included in this list, an account will be marked -offline as part of applying the block changes to the ledger. +Participation updates contains a two list of addressess of accounts +for which changes are made to their particpation status. + +The first contains accounts that have been deemed to be _expired_. An +account is said to be expired when the last valid vote round in its +participation key is strictly less than the current round that is +being processed. Once included in this list, an account will be +marked offline as part of applying the block changes to the ledger. + +The second contains accounts that have been deemed to be +_suspended_. An account is said to be suspended according to the rules +specified above for _suspended particpation accounts_ list. Once +included in this list, an account will be marked offline, but its +voting keys will be retained in the account state, as part of applying +the block changes to the ledger. + # Light Block Header @@ -585,7 +649,7 @@ contains the following components: # State Proof Tracking Each block header keeps track of the state needed to construct, validate, -and record state proofs. +and record state proofs. This tracking data is stored in a map under the msgpack key `spt` in the block header. The map is indexed by the type of the state proof; at the moment, only type 0 is supported. In the future, other types of state proofs @@ -692,6 +756,8 @@ transaction contains the following fields: - Transaction type `appl` corresponds to an _application call_ transaction. + - Transaction type `hb` corresponds to a _heartbeat_ transaction. + - The _sender_ $I$, which is an address which identifies the account that authorized the transaction. @@ -721,6 +787,10 @@ transaction contains the following fields: - The _note_ $N$, a sequence of bytes with length at most $N_{\max}$ which contains arbitrary data. +The cryptographic hash of all fields of the transaction, including the +transaction specific fields below, is called the _transaction +identifier_. This is written as $\Hash(\Tx)$. + ### Payment Transaction A payment transaction additionally has the following fields: @@ -888,9 +958,6 @@ An asset freeze transaction additionally has the following fields: encoded as a boolean msgpack field `afrz` (true for frozen, false for unfrozen). -The cryptographic hash of the fields above is called the _transaction -identifier_. This is written as $\Hash(\Tx)$. - ## State proof transaction A special transaction is used to disseminate and store state @@ -934,6 +1001,26 @@ When a state proof transaction is applied to the state, the next expected state A node should be able to verify state proof transaction at any point in time (even if `fv` is greater than next expected state proof round in the block header). +### Heartbeat Transaction + +A heartbeat transaction includes five additional fields encoded as a +struct under msgpack field `hb`. + + - The _heartbeat address_ $a$, an account address that this heartbeat + transaction proves liveness for. + + - The _heartbeat seed_ $sd$, which must be the block seed found in + the first valid block of the transaction. + + - The _heartbeat vote id_ $vid$, which must be the current public key + of the root voting key of the heartbeat address's account state. + + - The _heartbeat key dilution_ $kd$, which must be the current + $\KeyDilution$ of the heartbeat address's account state. + + - The _heartbeat proof_ $prf$, which must contain a valid signing of + $sd$ using $vid$ and $kd$ using the voting signature scheme + outlined in the discussion of [_participation keys_][partkey-spec]. Authorization and Signatures ---------------------------- @@ -1151,7 +1238,14 @@ the transactions have nonzero "Group", compute the _TxGroup hash_ as follows: If the TxGroup hash of any transaction group in a block does not match the "Group" field of the transactions in that group (and that "Group" field is nonzero), then the block is invalid. Additionally, if a block contains a transaction group of more than $G_{max}$ transactions, the block is invalid. -If the sum of the fees paid by the transactions in a transaction group is less than $f_{\min}$ times the number of transactions in the group, then the block is invalid. +If the sum of the fees paid by the transactions in a transaction group +is less than $f_{\min}$ times the number of transactions in the group, +then the block is invalid. There are two exceptions. State proof +transactions require no fee, and Heartbeat transaction require no fee +if they have a zero "Group" field, and the _heartbeat address_ was +challenged between 100 and 200 rounds ago, and has not proposed or +heartbeat since that challenge. Further explanation of this rule is +found in [Heartbeat Transaction Semantics] section, below. If the sum of the lengths of the boxes denoted by the box references in a transaction group exceeds 1,024 times the total number of box @@ -1390,6 +1484,26 @@ point must be discarded and the entire transaction rejected. will cause the program exection to fail. - Boxes may not be accessed by an app's `ClearStateProgram`. +## Heartbeat Transaction Semantics + + If a heartbeat transaction's $grp$ is empty, and $f < f_{min}$, the + transaction fails to execute unless: + + - The _note_ $N$ is empty + - The _lease_ $x$ is empty + - The _rekey to address_ $\RekeyTo$ is empty + - The _heartbeat_address_, $a$, is $online$ + - The _heartbeat_address_, $a$, $\ie$ flag is true + - The _heartbeat_address_, $a$, is _at risk_ of suspension + + An account is _at risk_ of suspension if the current round is between + 100-200 modulo 1000, and the blockseed of the most recent round that + is 0 modulo 1000 matches $a$ in the first 5 bits. + + If succesful, the `LastHeartbeat` of the specified heartbeat address + $a$ is updated to the current round. + + ## Validity and State Changes The new account state which results from applying a block is the account state @@ -1400,18 +1514,20 @@ the block's round $r$ and for the block's genesis identifier $\GenesisID_B$. For a transaction $$\Tx = (\GenesisID, \TxType, r_1, r_2, I, I', I_0, f, a, x, N, \pk, \sppk, \nonpart, \ldots)$$ -(where $\ldots$ represents fields specific to asset transaction types) +(where $\ldots$ represents fields specific to transaction types +besides "pay" and "keyreg") to be valid at the intermediate state $\rho$ in round $r$ for the genesis identifier $\GenesisID_B$, the following conditions must all hold: - It must represent a transition between two valid account states. - Either $\GenesisID = \GenesisID_B$ or $\GenesisID$ is the empty string. - - $\TxType$ is either "pay", "keyreg", "acfg", "axfer", "afrz" or "appl". + - $\TxType$ is either "pay", "keyreg", "acfg", "axfer", "afrz", + "appl", or "hb". - There are no extra fields that do not correspond to $\TxType$. - $0 \leq r_2 - r_1 \leq T_{\max}$. - $r_1 \leq r \leq r_2$. - $|N| \leq N_{\max}$. - - $I \neq I_{pool}$ and $I \neq 0$. + - $I \neq I_{pool}$, $I \neq I_f$, and $I \neq 0$. - $\Stake(r+1, I) \geq f \geq f_{\min}$. - The transaction is properly authorized as described in the [Authorization and Signatures][Authorization and Signatures] section. - $\Hash(\Tx) \notin \TxTail_r$. @@ -1445,6 +1561,7 @@ state for intermediate state $\rho+1$: - $p_{\rho+1, I} = 0$ if $\pk = 0$ and $\nonpart = \text{false}$ - $p_{\rho+1, I} = 2$ if $\pk = 0$ and $\nonpart = \text{true}$ - $p_{\rho+1, I} = 1$ if $\pk \ne 0$. + - If $f > 2000000$, then $\ie{\rho+1, I} = true$ - For $I'$ if $I \neq I'$ and either $I' \neq 0$ or $a \neq 0$: - $a_{\rho+1, I'} = \Stake(\rho+1, I') + a$. @@ -1458,8 +1575,8 @@ state for intermediate state $\rho+1$: (T_{r+1} - a'_{\rho, I_0}) \floor{\frac{a_{\rho, I_0}}{A}}$. - For all other $I^* \neq I$, the account state is identical to that in view $\rho$. -For asset transaction types (asset configuration, asset transfer, and asset freeze), -account state is updated based on the reference logic described in [Asset Transaction Semantics]. +For transaction types other than "pay" and "keyreg", account state is +updated based on the reference logic described below. Additionally, for all types of transactions, if the RekeyTo address of the transaction is nonzero and does not match the transaction sender address, then the transaction sender account's spending key is set to the RekeyTo address. If the RekeyTo address of the transaction does match the transaction sender address, then the transaction sender account's spending key is set to zero. From 2003916246cf6f333a6ab6f3ee60368b24cba786 Mon Sep 17 00:00:00 2001 From: John Jannotti Date: Thu, 19 Dec 2024 11:59:52 -0800 Subject: [PATCH 2/4] CR corrections --- dev/TEAL_opcodes.md | 8 ++++---- dev/ledger.md | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/dev/TEAL_opcodes.md b/dev/TEAL_opcodes.md index a968f26..d1e08ff 100644 --- a/dev/TEAL_opcodes.md +++ b/dev/TEAL_opcodes.md @@ -1113,10 +1113,10 @@ Fields Fields -| Index | Name | Type | In | Notes | -| - | ------ | -- | - | --------- | -| 0 | VoterBalance | uint64 | v6 | Online stake in microalgos | -| 1 | VoterIncentiveEligible | bool | | Had this account opted into block payouts | +| Index | Name | Type | Notes | +| - | ------ | -- | --------- | +| 0 | VoterBalance | uint64 | Online stake in microalgos | +| 1 | VoterIncentiveEligible | bool | Had this account opted into block payouts | ## online_stake diff --git a/dev/ledger.md b/dev/ledger.md index 4b6a5a8..608f530 100644 --- a/dev/ledger.md +++ b/dev/ledger.md @@ -1016,7 +1016,7 @@ struct under msgpack field `hb`. of the root voting key of the heartbeat address's account state. - The _heartbeat key dilution_ $kd$, which must be the current - $\KeyDilution$ of the heartbeat address's account state. + `KeyDilution` of the heartbeat address's account state. - The _heartbeat proof_ $prf$, which must contain a valid signing of $sd$ using $vid$ and $kd$ using the voting signature scheme @@ -1241,7 +1241,7 @@ If the TxGroup hash of any transaction group in a block does not match the "Grou If the sum of the fees paid by the transactions in a transaction group is less than $f_{\min}$ times the number of transactions in the group, then the block is invalid. There are two exceptions. State proof -transactions require no fee, and Heartbeat transaction require no fee +transactions require no fee, and Heartbeat transactions require no fee if they have a zero "Group" field, and the _heartbeat address_ was challenged between 100 and 200 rounds ago, and has not proposed or heartbeat since that challenge. Further explanation of this rule is @@ -1500,7 +1500,7 @@ point must be discarded and the entire transaction rejected. 100-200 modulo 1000, and the blockseed of the most recent round that is 0 modulo 1000 matches $a$ in the first 5 bits. - If succesful, the `LastHeartbeat` of the specified heartbeat address + If successful, the `LastHeartbeat` of the specified heartbeat address $a$ is updated to the current round. From 4a10f6f06fc1b76448526096b61b7ed2ef62aefa Mon Sep 17 00:00:00 2001 From: John Jannotti Date: Thu, 19 Dec 2024 12:43:45 -0800 Subject: [PATCH 3/4] mark not incentive eligible --- dev/ledger.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/dev/ledger.md b/dev/ledger.md index 608f530..20591b0 100644 --- a/dev/ledger.md +++ b/dev/ledger.md @@ -607,7 +607,8 @@ _suspended_. An account is said to be suspended according to the rules specified above for _suspended particpation accounts_ list. Once included in this list, an account will be marked offline, but its voting keys will be retained in the account state, as part of applying -the block changes to the ledger. +the block changes to the ledger. The `IncentiveEligible` flag of the +account will be set to false. # Light Block Header From 7f0786bd969f182635c780c7d5e76a109b051c95 Mon Sep 17 00:00:00 2001 From: John Jannotti Date: Thu, 19 Dec 2024 14:28:10 -0800 Subject: [PATCH 4/4] logicsig pooling --- dev/TEAL.md | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/dev/TEAL.md b/dev/TEAL.md index 3aa813d..3fc7ddc 100644 --- a/dev/TEAL.md +++ b/dev/TEAL.md @@ -145,14 +145,18 @@ of a contract account. transaction against the contract account is for the program to approve it. -The bytecode plus the length of all Args must add up to no more than -1000 bytes (consensus parameter LogicSigMaxSize). Each opcode has an -associated cost, usually 1, but a few slow operations have higher -costs. Prior to v4, the program's cost was estimated as the static sum -of all the opcode costs in the program (whether they were actually -executed or not). Beginning with v4, the program's cost is tracked -dynamically, while being evaluated. If the program exceeds its budget, -it fails. +The size of a Smart Signature is defined as the length of its bytecode +plus the length of all its Args. The sum of the sizes of all Smart +Signatures in a group must not exceed 1000 bytes times the number of +transactions in the group (1000 bytes is defined in consensus parameter +`LogicSigMaxSize`). + +Each opcode has an associated cost, usually 1, but a few slow operations +have higher costs. Prior to v4, the program's cost was estimated as the +static sum of all the opcode costs in the program (whether they were +actually executed or not). Beginning with v4, the program's cost is +tracked dynamically while being evaluated. If the program exceeds its +budget, it fails. The total program cost of all Smart Signatures in a group must not exceed 20,000 (consensus parameter LogicSigMaxCost) times the number