Skip to content

Commit

Permalink
Incentives: Updates for new heartbeat transaction type and latest con…
Browse files Browse the repository at this point in the history
…sensus v40 (#661)

* Updates for new heartbeat transaction type support.

* Sync heartbeat fields with go-algorand, make TxnHeartbeatFields explicit pointer type on Transaction.

* Sync consensus version settings with go-algorand.
  • Loading branch information
gmalouf authored Dec 20, 2024
1 parent 22ec6f5 commit 7237080
Show file tree
Hide file tree
Showing 6 changed files with 114 additions and 28 deletions.
65 changes: 44 additions & 21 deletions protocol/config/consensus.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ type ConsensusParams struct {
EnableAppCostPooling bool

// EnableLogicSigCostPooling specifies LogicSig budgets are pooled across a
// group. The total available is len(group) * LogicSigMaxCost)
// group. The total available is len(group) * LogicSigMaxCost
EnableLogicSigCostPooling bool

// EnableLogicSigSizePooling specifies LogicSig sizes are pooled across a
Expand Down Expand Up @@ -213,7 +213,7 @@ type ConsensusParams struct {
// 0 for no support, otherwise highest version supported
LogicSigVersion uint64

// len(LogicSig.Logic) + len(LogicSig.Args[*]) must be less than this
// len(LogicSig.Logic) + len(LogicSig.Args[*]) must be less than this (unless pooling is enabled)
LogicSigMaxSize uint64

// sum of estimated op cost must be less than this
Expand Down Expand Up @@ -495,6 +495,10 @@ type ConsensusParams struct {
// Version 7 includes state proof verification contexts
EnableCatchpointsWithSPContexts bool

// EnableCatchpointsWithOnlineAccounts specifies when to enable version 8 catchpoints.
// Version 8 includes onlineaccounts and onlineroundparams amounts, for historical stake lookups.
EnableCatchpointsWithOnlineAccounts bool

// AppForbidLowResources enforces a rule that prevents apps from accessing
// asas and apps below 256, in an effort to decrease the ambiguity of
// opcodes that accept IDs or slot indexes. Simultaneously, the first ID
Expand Down Expand Up @@ -525,6 +529,9 @@ type ConsensusParams struct {
// occur, extra funds need to be put into the FeeSink. The bonus amount
// decays exponentially.
Bonus BonusPlan

// Heartbeat support
Heartbeat bool
}

// ProposerPayoutRules puts several related consensus parameters in one place. The same
Expand Down Expand Up @@ -584,7 +591,7 @@ type ProposerPayoutRules struct {
//
// BaseAmount: 0, DecayInterval: XXX
//
// by using a zero baseAmount, the amount not affected.
// by using a zero baseAmount, the amount is not affected.
// For a bigger change, we'd use a plan like:
//
// BaseRound: <FUTURE round>, BaseAmount: <new amount>, DecayInterval: <new>
Expand Down Expand Up @@ -750,7 +757,7 @@ func checkSetAllocBounds(p ConsensusParams) {
checkSetMax(p.MaxAppProgramLen, &MaxStateDeltaKeys)
checkSetMax(p.MaxAppProgramLen, &MaxEvalDeltaAccounts)
checkSetMax(p.MaxAppProgramLen, &MaxAppProgramLen)
checkSetMax(int(p.LogicSigMaxSize), &MaxLogicSigMaxSize)
checkSetMax((int(p.LogicSigMaxSize) * p.MaxTxGroupSize), &MaxLogicSigMaxSize)
checkSetMax(p.MaxTxnNoteBytes, &MaxTxnNoteBytes)
checkSetMax(p.MaxTxGroupSize, &MaxTxGroupSize)
// MaxBytesKeyValueLen is max of MaxAppKeyLen and MaxAppBytesValueLen
Expand Down Expand Up @@ -1420,28 +1427,44 @@ func initConsensusProtocols() {
// but our current max is 150000 so using that :
v38.ApprovedUpgrades[protocol.ConsensusV39] = 150000

// ConsensusFuture is used to test features that are implemented
// but not yet released in a production protocol version.
vFuture := v39
vFuture.ApprovedUpgrades = map[protocol.ConsensusVersion]uint64{}
v40 := v39
v40.ApprovedUpgrades = map[protocol.ConsensusVersion]uint64{}

vFuture.LogicSigVersion = 11 // When moving this to a release, put a new higher LogicSigVersion here
v40.LogicSigVersion = 11

vFuture.EnableLogicSigSizePooling = true
v40.EnableLogicSigSizePooling = true

vFuture.Payouts.Enabled = true
vFuture.Payouts.Percent = 75
vFuture.Payouts.GoOnlineFee = 2_000_000 // 2 algos
vFuture.Payouts.MinBalance = 30_000_000_000 // 30,000 algos
vFuture.Payouts.MaxBalance = 70_000_000_000_000 // 70M algos
vFuture.Payouts.MaxMarkAbsent = 32
vFuture.Payouts.ChallengeInterval = 1000
vFuture.Payouts.ChallengeGracePeriod = 200
vFuture.Payouts.ChallengeBits = 5
v40.Payouts.Enabled = true
v40.Payouts.Percent = 50
v40.Payouts.GoOnlineFee = 2_000_000 // 2 algos
v40.Payouts.MinBalance = 30_000_000_000 // 30,000 algos
v40.Payouts.MaxBalance = 70_000_000_000_000 // 70M algos
v40.Payouts.MaxMarkAbsent = 32
v40.Payouts.ChallengeInterval = 1000
v40.Payouts.ChallengeGracePeriod = 200
v40.Payouts.ChallengeBits = 5

vFuture.Bonus.BaseAmount = 10_000_000 // 10 Algos
v40.Bonus.BaseAmount = 10_000_000 // 10 Algos
// 2.9 sec rounds gives about 10.8M rounds per year.
vFuture.Bonus.DecayInterval = 250_000 // .99^(10.8/0.25) ~ .648. So 35% decay per year
v40.Bonus.DecayInterval = 1_000_000 // .99^(10.8M/1M) ~ .897. So ~10% decay per year

v40.Heartbeat = true

v40.EnableCatchpointsWithOnlineAccounts = true

Consensus[protocol.ConsensusV40] = v40

// v39 can be upgraded to v40, with an update delay of 7d:
// 208000 = (7 * 24 * 60 * 60 / 2.9 ballpark round times)
// our current max is 250000
v39.ApprovedUpgrades[protocol.ConsensusV40] = 208000

// ConsensusFuture is used to test features that are implemented
// but not yet released in a production protocol version.
vFuture := v40
vFuture.ApprovedUpgrades = map[protocol.ConsensusVersion]uint64{}

vFuture.LogicSigVersion = 12 // When moving this to a release, put a new higher LogicSigVersion here

Consensus[protocol.ConsensusFuture] = vFuture

Expand Down
7 changes: 6 additions & 1 deletion protocol/consensus.go
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,11 @@ const ConsensusV39 = ConsensusVersion(
"https://github.com/algorandfoundation/specs/tree/925a46433742afb0b51bb939354bd907fa88bf95",
)

// ConsensusV40 enables consensus incentives and TEAL v11 featuring the mimc opcode
const ConsensusV40 = ConsensusVersion(
"https://github.com/algorandfoundation/specs/tree/236dcc18c9c507d794813ab768e467ea42d1b4d9",
)

// ConsensusFuture is a protocol that should not appear in any production
// network, but is used to test features before they are released.
const ConsensusFuture = ConsensusVersion(
Expand Down Expand Up @@ -230,7 +235,7 @@ const ConsensusVAlpha5 = ConsensusVersion("alpha5")

// ConsensusCurrentVersion is the latest version and should be used
// when a specific version is not provided.
const ConsensusCurrentVersion = ConsensusV39
const ConsensusCurrentVersion = ConsensusV40

// Error is used to indicate that an unsupported protocol has been detected.
type Error ConsensusVersion
Expand Down
8 changes: 2 additions & 6 deletions types/basics.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,19 +30,15 @@ const (
ApplicationCallTx TxType = "appl"
// StateProofTx records a state proof
StateProofTx TxType = "stpf"
// HeartbeatTx demonstrates the account is alive
HeartbeatTx TxType = "hb"
)

const masterDerivationKeyLenBytes = 32

// MaxTxGroupSize is max number of transactions in a single group
const MaxTxGroupSize = 16

// LogicSigMaxSize is a max TEAL program size (with args)
const LogicSigMaxSize = 1000

// LogicSigMaxCost is a max execution const of a TEAL program
const LogicSigMaxCost = 20000

// KeyStoreRootSize is the size, in bytes, of keyreg verifier
const KeyStoreRootSize = 64

Expand Down
27 changes: 27 additions & 0 deletions types/heartbeat.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package types

// HeartbeatTxnFields captures the fields used for an account to prove it is
// online (really, it proves that an entity with the account's part keys is able
// to submit transactions, so it should be able to propose/vote.)
type HeartbeatTxnFields struct {
_struct struct{} `codec:",omitempty,omitemptyarray"`

// HeartbeatAddress is the account this txn is proving onlineness for.
HbAddress Address `codec:"a"`

// HbProof is a signature using HeartbeatAddress's partkey, thereby showing it is online.
HbProof HeartbeatProof `codec:"prf"`

// The final three fields are included to allow early, concurrent check of
// the HbProof.

// HbSeed must be the block seed for this transaction's firstValid
// block. It is the message that must be signed with HbAddress's part key.
HbSeed Seed `codec:"sd"`

// HbVoteID must match the HbAddress account's current VoteID.
HbVoteID OneTimeSignatureVerifier `codec:"vid"`

// HbKeyDilution must match HbAddress account's current KeyDilution.
HbKeyDilution uint64 `codec:"kd"`
}
30 changes: 30 additions & 0 deletions types/signature.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,3 +79,33 @@ func (lsig LogicSig) Blank() bool {
}
return true
}

/* Classical signatures */
type ed25519Signature [64]byte
type ed25519PublicKey [32]byte

// A HeartbeatProof is functionally equivalent to a OneTimeSignature (see below), but it has
// been cleaned up for use as a transaction field in heartbeat transactions.
//
// A OneTimeSignature is a cryptographic signature that is produced a limited
// number of times and provides forward integrity.
//
// Specifically, a OneTimeSignature is generated from an ephemeral secret. After
// some number of messages is signed under a given OneTimeSignatureIdentifier
// identifier, the corresponding secret is deleted. This prevents the
// secret-holder from signing a contradictory message in the future in the event
// of a secret-key compromise.
type HeartbeatProof struct {
_struct struct{} `codec:",omitempty,omitemptyarray"`

// Sig is a signature of msg under the key PK.
Sig ed25519Signature `codec:"s"`
PK ed25519PublicKey `codec:"p"`

// PK2 is used to verify a two-level ephemeral signature.
PK2 ed25519PublicKey `codec:"p2"`
// PK1Sig is a signature of OneTimeSignatureSubkeyOffsetID(PK, Batch, Offset) under the key PK2.
PK1Sig ed25519Signature `codec:"p1s"`
// PK2Sig is a signature of OneTimeSignatureSubkeyBatchID(PK2, Batch) under the master key (OneTimeSignatureVerifier).
PK2Sig ed25519Signature `codec:"p2s"`
}
5 changes: 5 additions & 0 deletions types/transaction.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@ type Transaction struct {
AssetFreezeTxnFields
ApplicationFields
StateProofTxnFields

// By making HeartbeatTxnFields a pointer we save a ton of space of the
// Transaction object. Unlike other txn types, the fields will be
// embedded under a named field in the transaction encoding.
*HeartbeatTxnFields `codec:"hb"`
}

// SignedTxn wraps a transaction and a signature. The encoding of this struct
Expand Down

0 comments on commit 7237080

Please sign in to comment.