summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Jannotti <jannotti@gmail.com>2023-12-07 18:11:46 -0500
committerGitHub <noreply@github.com>2023-12-07 18:11:46 -0500
commitb37fadbd1b14e9e1455b6eb9ecb27535a094c20a (patch)
tree167deb84521d7e027306d8d224271a338de0c221
parent9229066ea56b1f8713385b905006e8ba09265cef (diff)
AVM: Add `global GenesisHash` (#5858)
-rw-r--r--cmd/tealdbg/localLedger.go4
-rw-r--r--daemon/algod/api/server/v2/dryrun.go5
-rw-r--r--data/transactions/logic/README.md1
-rw-r--r--data/transactions/logic/TEAL_opcodes_v10.md1
-rw-r--r--data/transactions/logic/assembler_test.go18
-rw-r--r--data/transactions/logic/eval.go23
-rw-r--r--data/transactions/logic/evalAppTxn_test.go31
-rw-r--r--data/transactions/logic/evalStateful_test.go10
-rw-r--r--data/transactions/logic/fields.go5
-rw-r--r--data/transactions/logic/fields_string.go7
-rw-r--r--data/transactions/logic/fields_test.go58
-rw-r--r--data/transactions/logic/langspec_v10.json6
-rw-r--r--data/transactions/logic/ledger_test.go8
-rw-r--r--data/transactions/logic/teal.tmLanguage.json2
-rw-r--r--data/transactions/verify/txn_test.go3
-rw-r--r--ledger/eval/appcow_test.go5
-rw-r--r--ledger/eval/cow.go6
-rw-r--r--ledger/eval/cow_test.go5
-rw-r--r--ledger/eval/eval.go5
-rw-r--r--ledger/eval/eval_test.go4
20 files changed, 184 insertions, 23 deletions
diff --git a/cmd/tealdbg/localLedger.go b/cmd/tealdbg/localLedger.go
index 64dfe7329..fc7655173 100644
--- a/cmd/tealdbg/localLedger.go
+++ b/cmd/tealdbg/localLedger.go
@@ -281,6 +281,10 @@ func (l *localLedger) BlockHdr(basics.Round) (bookkeeping.BlockHeader, error) {
return bookkeeping.BlockHeader{}, nil
}
+func (l *localLedger) GenesisHash() crypto.Digest {
+ return crypto.Digest{}
+}
+
func (l *localLedger) GetStateProofVerificationContext(_ basics.Round) (*ledgercore.StateProofVerificationContext, error) {
return nil, fmt.Errorf("localLedger: GetStateProofVerificationContext, needed for state proof verification, is not implemented in debugger")
}
diff --git a/daemon/algod/api/server/v2/dryrun.go b/daemon/algod/api/server/v2/dryrun.go
index ef0de8085..acf5fc94b 100644
--- a/daemon/algod/api/server/v2/dryrun.go
+++ b/daemon/algod/api/server/v2/dryrun.go
@@ -22,6 +22,7 @@ import (
"strings"
"github.com/algorand/go-algorand/config"
+ "github.com/algorand/go-algorand/crypto"
"github.com/algorand/go-algorand/daemon/algod/api/server/v2/generated/model"
"github.com/algorand/go-algorand/data/basics"
"github.com/algorand/go-algorand/data/bookkeeping"
@@ -241,6 +242,10 @@ func (dl *dryrunLedger) BlockHdr(basics.Round) (bookkeeping.BlockHeader, error)
return bookkeeping.BlockHeader{}, nil
}
+func (dl *dryrunLedger) GenesisHash() crypto.Digest {
+ return crypto.Digest{}
+}
+
func (dl *dryrunLedger) CheckDup(config.ConsensusParams, basics.Round, basics.Round, basics.Round, transactions.Txid, ledgercore.Txlease) error {
return nil
}
diff --git a/data/transactions/logic/README.md b/data/transactions/logic/README.md
index da4fdefac..a38ba1462 100644
--- a/data/transactions/logic/README.md
+++ b/data/transactions/logic/README.md
@@ -633,6 +633,7 @@ Global fields are fields that are common to all the transactions in the group. I
| 14 | CallerApplicationAddress | address | v6 | The application address of the application that called this application. ZeroAddress if this application is at the top-level. Application mode only. |
| 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. |
**Asset Fields**
diff --git a/data/transactions/logic/TEAL_opcodes_v10.md b/data/transactions/logic/TEAL_opcodes_v10.md
index 7df81c33a..81d742fbd 100644
--- a/data/transactions/logic/TEAL_opcodes_v10.md
+++ b/data/transactions/logic/TEAL_opcodes_v10.md
@@ -461,6 +461,7 @@ Fields
| 14 | CallerApplicationAddress | address | v6 | The application address of the application that called this application. ZeroAddress if this application is at the top-level. Application mode only. |
| 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. |
## gtxn
diff --git a/data/transactions/logic/assembler_test.go b/data/transactions/logic/assembler_test.go
index 4fdcaae61..0963ee148 100644
--- a/data/transactions/logic/assembler_test.go
+++ b/data/transactions/logic/assembler_test.go
@@ -1686,17 +1686,19 @@ txn NumApprovalProgramPages
txna ApprovalProgramPages 0
txn NumClearStateProgramPages
txna ClearStateProgramPages 0
+pushint 1
+block BlkTimestamp
+pushint 1
+block BlkSeed
global AssetCreateMinBalance
global AssetOptInMinBalance
+global GenesisHash
`, AssemblerMaxVersion)
- for _, globalField := range GlobalFieldNames {
- if !strings.Contains(text, globalField) {
- t.Errorf("TestAssembleDisassemble missing field global %v", globalField)
- }
- }
- for _, txnField := range TxnFieldNames {
- if !strings.Contains(text, txnField) {
- t.Errorf("TestAssembleDisassemble missing field txn %v", txnField)
+ for _, names := range [][]string{GlobalFieldNames[:], TxnFieldNames[:], blockFieldNames[:]} {
+ for _, f := range names {
+ if !strings.Contains(text, f) {
+ t.Errorf("TestAssembleDisassemble missing field %v", f)
+ }
}
}
ops := testProg(t, text, AssemblerMaxVersion)
diff --git a/data/transactions/logic/eval.go b/data/transactions/logic/eval.go
index 0e1faec0d..883eddcec 100644
--- a/data/transactions/logic/eval.go
+++ b/data/transactions/logic/eval.go
@@ -200,10 +200,12 @@ func computeMinAvmVersion(group []transactions.SignedTxnWithAD) uint64 {
// "stateless" for signature purposes.
type LedgerForSignature interface {
BlockHdr(basics.Round) (bookkeeping.BlockHeader, error)
+ GenesisHash() crypto.Digest
}
-// NoHeaderLedger is intended for debugging situations in which it is reasonable
-// to preclude the use of `block` and `txn LastValidTime`
+// NoHeaderLedger is intended for debugging TEAL in isolation(no real ledger) in
+// which it is reasonable to preclude the use of `block`, `txn
+// LastValidTime`. Also `global GenesisHash` is just a static value.
type NoHeaderLedger struct {
}
@@ -212,6 +214,16 @@ func (NoHeaderLedger) BlockHdr(basics.Round) (bookkeeping.BlockHeader, error) {
return bookkeeping.BlockHeader{}, fmt.Errorf("no block header access")
}
+// GenesisHash returns a fixed value
+func (NoHeaderLedger) GenesisHash() crypto.Digest {
+ return crypto.Digest{
+ 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
+ 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
+ 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
+ 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
+ }
+}
+
// LedgerForLogic represents ledger API for Stateful TEAL program
type LedgerForLogic interface {
AccountData(addr basics.Address) (ledgercore.AccountData, error)
@@ -3610,8 +3622,11 @@ func (cx *EvalContext) globalFieldToValue(fs globalFieldSpec) (sv stackValue, er
sv.Uint = cx.Proto.MinBalance
case AssetOptInMinBalance:
sv.Uint = cx.Proto.MinBalance
+ case GenesisHash:
+ gh := cx.SigLedger.GenesisHash()
+ sv.Bytes = gh[:]
default:
- err = fmt.Errorf("invalid global field %d", fs.field)
+ return sv, fmt.Errorf("invalid global field %s", fs.field)
}
if fs.ftype.AVMType != sv.avmType() {
@@ -5587,7 +5602,7 @@ func opBlock(cx *EvalContext) error {
cx.Stack[last].Uint = uint64(hdr.TimeStamp)
return nil
default:
- return fmt.Errorf("invalid block field %d", fs.field)
+ return fmt.Errorf("invalid block field %s", fs.field)
}
}
diff --git a/data/transactions/logic/evalAppTxn_test.go b/data/transactions/logic/evalAppTxn_test.go
index 06fee09c1..4682732fb 100644
--- a/data/transactions/logic/evalAppTxn_test.go
+++ b/data/transactions/logic/evalAppTxn_test.go
@@ -575,6 +575,37 @@ func TestBadField(t *testing.T) {
TestAppBytes(t, ops.Program, ep, "invalid itxn_field FirstValid")
}
+// TestInnerValidity logs fv and lv fields that are handled oddly (valid
+// rounds are copied) so we can check if they are correct.
+func TestInnerValidity(t *testing.T) {
+ partitiontest.PartitionTest(t)
+ t.Parallel()
+ ep, tx, ledger := MakeSampleEnv()
+ tx.GenesisHash = crypto.Digest{0x01, 0x02, 0x03}
+ logger := TestProg(t, `
+txn FirstValid; itob; log;
+txn LastValid; itob; log;
+int 1`, AssemblerMaxVersion)
+ ledger.NewApp(tx.Receiver, 222, basics.AppParams{
+ ApprovalProgram: logger.Program,
+ })
+
+ ledger.NewAccount(appAddr(888), 50_000)
+ tx.ForeignApps = []basics.AppIndex{basics.AppIndex(222)}
+ TestApp(t, `
+itxn_begin
+int appl; itxn_field TypeEnum
+int 222; itxn_field ApplicationID
+itxn_submit
+itxn Logs 0; btoi; txn FirstValid; ==; assert
+itxn Logs 1; btoi; txn LastValid; ==; assert
+itxn FirstValid; txn FirstValid; ==; assert
+itxn LastValid; txn LastValid; ==; assert
+int 1
+`, ep)
+
+}
+
func TestNumInnerShallow(t *testing.T) {
partitiontest.PartitionTest(t)
t.Parallel()
diff --git a/data/transactions/logic/evalStateful_test.go b/data/transactions/logic/evalStateful_test.go
index 436643e4c..d25851be0 100644
--- a/data/transactions/logic/evalStateful_test.go
+++ b/data/transactions/logic/evalStateful_test.go
@@ -3435,6 +3435,14 @@ func TestLatestTimestamp(t *testing.T) {
testApp(t, source, ep)
}
+func TestGenHash(t *testing.T) {
+ partitiontest.PartitionTest(t)
+ t.Parallel()
+ ep, _, _ := makeSampleEnv()
+ source := fmt.Sprintf("global GenesisHash; byte 0x%s; ==", hex.EncodeToString(testGenHash[:]))
+ testApp(t, source, ep)
+}
+
func TestBlockSeed(t *testing.T) {
partitiontest.PartitionTest(t)
t.Parallel()
@@ -3465,7 +3473,7 @@ func TestBlockSeed(t *testing.T) {
testApp(t, "int 4294967310; int 1502; -; block BlkSeed; len; int 32; ==", ep,
"not available") // 1501 back from lv is not
- // A little silly, as it only tests the test ledger: ensure samenes and differentness
+ // A little silly, as it only tests the test ledger: ensure sameness and differentness
testApp(t, "int 0xfffffff0; block BlkSeed; int 0xfffffff0; block BlkSeed; ==", ep)
testApp(t, "int 0xfffffff0; block BlkSeed; int 0xfffffff1; block BlkSeed; !=", ep)
diff --git a/data/transactions/logic/fields.go b/data/transactions/logic/fields.go
index bb5c2179e..060516d65 100644
--- a/data/transactions/logic/fields.go
+++ b/data/transactions/logic/fields.go
@@ -535,6 +535,9 @@ const (
// AssetOptInMinBalance is the additional minimum balance required to opt in to an asset
AssetOptInMinBalance
+ // GenesisHash is the genesis hash for the network
+ GenesisHash
+
invalidGlobalField // compile-time constant for number of fields
)
@@ -599,6 +602,7 @@ var globalFieldSpecs = [...]globalFieldSpec{
"The additional minimum balance required to create (and opt-in to) an asset."},
{AssetOptInMinBalance, StackUint64, modeAny, 10,
"The additional minimum balance required to opt-in to an asset."},
+ {GenesisHash, StackBytes32, modeAny, 10, "The Genesis Hash for the network."},
}
func globalFieldSpecByField(f GlobalField) (globalFieldSpec, bool) {
@@ -961,6 +965,7 @@ const (
BlkSeed BlockField = iota
// BlkTimestamp is the Block's timestamp, seconds from epoch
BlkTimestamp
+
invalidBlockField // compile-time constant for number of fields
)
diff --git a/data/transactions/logic/fields_string.go b/data/transactions/logic/fields_string.go
index 7d3c2b42f..37bfeb9bc 100644
--- a/data/transactions/logic/fields_string.go
+++ b/data/transactions/logic/fields_string.go
@@ -110,12 +110,13 @@ func _() {
_ = x[CallerApplicationAddress-14]
_ = x[AssetCreateMinBalance-15]
_ = x[AssetOptInMinBalance-16]
- _ = x[invalidGlobalField-17]
+ _ = x[GenesisHash-17]
+ _ = x[invalidGlobalField-18]
}
-const _GlobalField_name = "MinTxnFeeMinBalanceMaxTxnLifeZeroAddressGroupSizeLogicSigVersionRoundLatestTimestampCurrentApplicationIDCreatorAddressCurrentApplicationAddressGroupIDOpcodeBudgetCallerApplicationIDCallerApplicationAddressAssetCreateMinBalanceAssetOptInMinBalanceinvalidGlobalField"
+const _GlobalField_name = "MinTxnFeeMinBalanceMaxTxnLifeZeroAddressGroupSizeLogicSigVersionRoundLatestTimestampCurrentApplicationIDCreatorAddressCurrentApplicationAddressGroupIDOpcodeBudgetCallerApplicationIDCallerApplicationAddressAssetCreateMinBalanceAssetOptInMinBalanceGenesisHashinvalidGlobalField"
-var _GlobalField_index = [...]uint16{0, 9, 19, 29, 40, 49, 64, 69, 84, 104, 118, 143, 150, 162, 181, 205, 226, 246, 264}
+var _GlobalField_index = [...]uint16{0, 9, 19, 29, 40, 49, 64, 69, 84, 104, 118, 143, 150, 162, 181, 205, 226, 246, 257, 275}
func (i GlobalField) String() string {
if i >= GlobalField(len(_GlobalField_index)-1) {
diff --git a/data/transactions/logic/fields_test.go b/data/transactions/logic/fields_test.go
index f4736f621..2fd432956 100644
--- a/data/transactions/logic/fields_test.go
+++ b/data/transactions/logic/fields_test.go
@@ -112,6 +112,19 @@ func TestTxnFieldVersions(t *testing.T) {
asmError = "...txna opcode was introduced in ..."
txnaMode = true
}
+
+ // tack on a type check, and return a value (`int` gets compiled
+ // differently in different versions, so use `txn FirstValid` to get
+ // a positive integer)
+ switch fs.ftype.AVMType {
+ case avmUint64: // ensure the return type is uint64 by using !
+ text += "; !; pop; txn FirstValid"
+ case avmBytes: // ensure the return type is bytes by using len
+ text += "; len; pop; txn FirstValid"
+ case avmAny:
+ text += "; pop; txn FirstValid"
+ }
+
// check assembler fails if version before introduction
testLine(t, text, assemblerNoVersion, asmError)
for v := uint64(0); v < fs.version; v++ {
@@ -124,6 +137,18 @@ func TestTxnFieldVersions(t *testing.T) {
ops := testProg(t, text, AssemblerMaxVersion)
+ // check success in AssemblerMaxVersion, fs.version
+ // also ensures the field returns the right type
+ if !fs.effects {
+ txgroup[0].Txn.ApprovalProgram = []byte("approve") // not in standard sample txn
+ txgroup[0].Txn.ClearStateProgram = []byte("clear")
+ ep := defaultAppParamsWithVersion(AssemblerMaxVersion, txgroup...)
+ testAppBytes(t, ops.Program, ep)
+ opsv := testProg(t, text, fs.version)
+ ep = defaultAppParamsWithVersion(fs.version, txgroup...)
+ testAppBytes(t, opsv.Program, ep)
+ }
+
preVersion := fs.version - 1
ep := defaultSigParamsWithVersion(preVersion, txgroup...)
@@ -283,3 +308,36 @@ func TestAcctParamsFieldsVersions(t *testing.T) {
}
}
+
+func TestBlockFieldsVersions(t *testing.T) {
+ partitiontest.PartitionTest(t)
+ t.Parallel()
+
+ for _, field := range blockFieldSpecs {
+ text := fmt.Sprintf("txn FirstValid; int 1; - ; block %s;", field.field)
+ if field.ftype.AVMType == avmBytes {
+ text += "global ZeroAddress; concat; len" // use concat to prove we have bytes
+ } else {
+ text += "global ZeroAddress; len; +" // use + to prove we have an int
+ }
+
+ testLogicRange(t, 4, 0, func(t *testing.T, ep *EvalParams, txn *transactions.Transaction, ledger *Ledger) {
+ v := ep.Proto.LogicSigVersion
+ if field.version > v {
+ // check assembler fails if version before introduction
+ testProg(t, text, v, exp(1, "...was introduced in..."))
+ ops := testProg(t, text, field.version) // assemble in the future
+ ops.Program[0] = byte(v) // but set version back to before intro
+ if v < randomnessVersion {
+ testAppBytes(t, ops.Program, ep, "illegal opcode", "illegal opcode")
+ } else {
+ testAppBytes(t, ops.Program, ep, "invalid block field")
+ }
+ } else {
+ testProg(t, text, v)
+ testApp(t, text, ep)
+ }
+ })
+
+ }
+}
diff --git a/data/transactions/logic/langspec_v10.json b/data/transactions/logic/langspec_v10.json
index affe46601..2141e8fe0 100644
--- a/data/transactions/logic/langspec_v10.json
+++ b/data/transactions/logic/langspec_v10.json
@@ -1196,7 +1196,8 @@
"CallerApplicationID",
"CallerApplicationAddress",
"AssetCreateMinBalance",
- "AssetOptInMinBalance"
+ "AssetOptInMinBalance",
+ "GenesisHash"
],
"ArgEnumTypes": [
"uint64",
@@ -1215,7 +1216,8 @@
"uint64",
"address",
"uint64",
- "uint64"
+ "uint64",
+ "[32]byte"
],
"DocCost": "1",
"Doc": "global field F",
diff --git a/data/transactions/logic/ledger_test.go b/data/transactions/logic/ledger_test.go
index a111eec13..a575c493d 100644
--- a/data/transactions/logic/ledger_test.go
+++ b/data/transactions/logic/ledger_test.go
@@ -36,6 +36,7 @@ import (
"math"
"math/rand"
+ "github.com/algorand/go-algorand/crypto"
"github.com/algorand/go-algorand/data/basics"
"github.com/algorand/go-algorand/data/bookkeeping"
"github.com/algorand/go-algorand/data/committee"
@@ -607,6 +608,13 @@ func (l *Ledger) AppParams(appID basics.AppIndex) (basics.AppParams, basics.Addr
return basics.AppParams{}, basics.Address{}, fmt.Errorf("no app %d", appID)
}
+var testGenHash = crypto.Digest{0x03, 0x02, 0x03}
+
+// GenesisHash returns a phony genesis hash that can be tested against
+func (l *Ledger) GenesisHash() crypto.Digest {
+ return testGenHash
+}
+
func (l *Ledger) move(from basics.Address, to basics.Address, amount uint64) error {
fbr, ok := l.balances[from]
if !ok {
diff --git a/data/transactions/logic/teal.tmLanguage.json b/data/transactions/logic/teal.tmLanguage.json
index ef80fd048..e414922e8 100644
--- a/data/transactions/logic/teal.tmLanguage.json
+++ b/data/transactions/logic/teal.tmLanguage.json
@@ -112,7 +112,7 @@
},
{
"name": "variable.parameter.teal",
- "match": "\\b(unknown|pay|keyreg|acfg|axfer|afrz|appl|NoOp|OptIn|CloseOut|ClearState|UpdateApplication|DeleteApplication|Secp256k1|Secp256r1|Sender|Fee|FirstValid|FirstValidTime|LastValid|Note|Lease|Receiver|Amount|CloseRemainderTo|VotePK|SelectionPK|VoteFirst|VoteLast|VoteKeyDilution|Type|TypeEnum|XferAsset|AssetAmount|AssetSender|AssetReceiver|AssetCloseTo|GroupIndex|TxID|ApplicationID|OnCompletion|NumAppArgs|NumAccounts|ApprovalProgram|ClearStateProgram|RekeyTo|ConfigAsset|ConfigAssetTotal|ConfigAssetDecimals|ConfigAssetDefaultFrozen|ConfigAssetUnitName|ConfigAssetName|ConfigAssetURL|ConfigAssetMetadataHash|ConfigAssetManager|ConfigAssetReserve|ConfigAssetFreeze|ConfigAssetClawback|FreezeAsset|FreezeAssetAccount|FreezeAssetFrozen|NumAssets|NumApplications|GlobalNumUint|GlobalNumByteSlice|LocalNumUint|LocalNumByteSlice|ExtraProgramPages|Nonparticipation|NumLogs|CreatedAssetID|CreatedApplicationID|LastLog|StateProofPK|NumApprovalProgramPages|NumClearStateProgramPages|MinTxnFee|MinBalance|MaxTxnLife|ZeroAddress|GroupSize|LogicSigVersion|Round|LatestTimestamp|CurrentApplicationID|CreatorAddress|CurrentApplicationAddress|GroupID|OpcodeBudget|CallerApplicationID|CallerApplicationAddress|AssetCreateMinBalance|AssetOptInMinBalance|ApplicationArgs|Accounts|Assets|Applications|Logs|ApprovalProgramPages|ClearStateProgramPages|URLEncoding|StdEncoding|JSONString|JSONUint64|JSONObject|AssetBalance|AssetFrozen|AssetTotal|AssetDecimals|AssetDefaultFrozen|AssetUnitName|AssetName|AssetURL|AssetMetadataHash|AssetManager|AssetReserve|AssetFreeze|AssetClawback|AssetCreator|AppApprovalProgram|AppClearStateProgram|AppGlobalNumUint|AppGlobalNumByteSlice|AppLocalNumUint|AppLocalNumByteSlice|AppExtraProgramPages|AppCreator|AppAddress|AcctBalance|AcctMinBalance|AcctAuthAddr|AcctTotalNumUint|AcctTotalNumByteSlice|AcctTotalExtraAppPages|AcctTotalAppsCreated|AcctTotalAppsOptedIn|AcctTotalAssetsCreated|AcctTotalAssets|AcctTotalBoxes|AcctTotalBoxBytes|VrfAlgorand|BlkSeed|BlkTimestamp|BN254g1|BN254g2|BLS12_381g1|BLS12_381g2)\\b"
+ "match": "\\b(unknown|pay|keyreg|acfg|axfer|afrz|appl|NoOp|OptIn|CloseOut|ClearState|UpdateApplication|DeleteApplication|Secp256k1|Secp256r1|Sender|Fee|FirstValid|FirstValidTime|LastValid|Note|Lease|Receiver|Amount|CloseRemainderTo|VotePK|SelectionPK|VoteFirst|VoteLast|VoteKeyDilution|Type|TypeEnum|XferAsset|AssetAmount|AssetSender|AssetReceiver|AssetCloseTo|GroupIndex|TxID|ApplicationID|OnCompletion|NumAppArgs|NumAccounts|ApprovalProgram|ClearStateProgram|RekeyTo|ConfigAsset|ConfigAssetTotal|ConfigAssetDecimals|ConfigAssetDefaultFrozen|ConfigAssetUnitName|ConfigAssetName|ConfigAssetURL|ConfigAssetMetadataHash|ConfigAssetManager|ConfigAssetReserve|ConfigAssetFreeze|ConfigAssetClawback|FreezeAsset|FreezeAssetAccount|FreezeAssetFrozen|NumAssets|NumApplications|GlobalNumUint|GlobalNumByteSlice|LocalNumUint|LocalNumByteSlice|ExtraProgramPages|Nonparticipation|NumLogs|CreatedAssetID|CreatedApplicationID|LastLog|StateProofPK|NumApprovalProgramPages|NumClearStateProgramPages|MinTxnFee|MinBalance|MaxTxnLife|ZeroAddress|GroupSize|LogicSigVersion|Round|LatestTimestamp|CurrentApplicationID|CreatorAddress|CurrentApplicationAddress|GroupID|OpcodeBudget|CallerApplicationID|CallerApplicationAddress|AssetCreateMinBalance|AssetOptInMinBalance|GenesisHash|ApplicationArgs|Accounts|Assets|Applications|Logs|ApprovalProgramPages|ClearStateProgramPages|URLEncoding|StdEncoding|JSONString|JSONUint64|JSONObject|AssetBalance|AssetFrozen|AssetTotal|AssetDecimals|AssetDefaultFrozen|AssetUnitName|AssetName|AssetURL|AssetMetadataHash|AssetManager|AssetReserve|AssetFreeze|AssetClawback|AssetCreator|AppApprovalProgram|AppClearStateProgram|AppGlobalNumUint|AppGlobalNumByteSlice|AppLocalNumUint|AppLocalNumByteSlice|AppExtraProgramPages|AppCreator|AppAddress|AcctBalance|AcctMinBalance|AcctAuthAddr|AcctTotalNumUint|AcctTotalNumByteSlice|AcctTotalExtraAppPages|AcctTotalAppsCreated|AcctTotalAppsOptedIn|AcctTotalAssetsCreated|AcctTotalAssets|AcctTotalBoxes|AcctTotalBoxBytes|VrfAlgorand|BlkSeed|BlkTimestamp|BN254g1|BN254g2|BLS12_381g1|BLS12_381g2)\\b"
}
]
},
diff --git a/data/transactions/verify/txn_test.go b/data/transactions/verify/txn_test.go
index 416c0e4c0..d2061b872 100644
--- a/data/transactions/verify/txn_test.go
+++ b/data/transactions/verify/txn_test.go
@@ -78,6 +78,9 @@ func (d *DummyLedgerForSignature) BlockHdr(rnd basics.Round) (blk bookkeeping.Bl
}
return createDummyBlockHeader(), nil
}
+func (d *DummyLedgerForSignature) GenesisHash() crypto.Digest {
+ return crypto.Digest{}
+}
func (d *DummyLedgerForSignature) Latest() basics.Round {
return 0
}
diff --git a/ledger/eval/appcow_test.go b/ledger/eval/appcow_test.go
index 2c46d02c0..a4c8d22c6 100644
--- a/ledger/eval/appcow_test.go
+++ b/ledger/eval/appcow_test.go
@@ -25,6 +25,7 @@ import (
"github.com/stretchr/testify/require"
"github.com/algorand/go-algorand/config"
+ "github.com/algorand/go-algorand/crypto"
"github.com/algorand/go-algorand/data/basics"
"github.com/algorand/go-algorand/data/bookkeeping"
"github.com/algorand/go-algorand/data/transactions"
@@ -99,8 +100,8 @@ func (ml *emptyLedger) BlockHdr(rnd basics.Round) (bookkeeping.BlockHeader, erro
return bookkeeping.BlockHeader{}, nil
}
-func (ml *emptyLedger) blockHdrCached(rnd basics.Round) (bookkeeping.BlockHeader, error) {
- return bookkeeping.BlockHeader{}, nil
+func (ml *emptyLedger) GenesisHash() crypto.Digest {
+ return crypto.Digest{}
}
func (ml *emptyLedger) GetStateProofNextRound() basics.Round {
diff --git a/ledger/eval/cow.go b/ledger/eval/cow.go
index d797a4a56..f3e6b3d04 100644
--- a/ledger/eval/cow.go
+++ b/ledger/eval/cow.go
@@ -22,6 +22,7 @@ import (
"sync"
"github.com/algorand/go-algorand/config"
+ "github.com/algorand/go-algorand/crypto"
"github.com/algorand/go-algorand/data/basics"
"github.com/algorand/go-algorand/data/bookkeeping"
"github.com/algorand/go-algorand/data/transactions"
@@ -65,6 +66,7 @@ type roundCowParent interface {
getKey(addr basics.Address, aidx basics.AppIndex, global bool, key string, accountIdx uint64) (basics.TealValue, bool, error)
kvGet(key string) ([]byte, bool, error)
GetStateProofVerificationContext(stateProofLastAttestedRound basics.Round) (*ledgercore.StateProofVerificationContext, error)
+ GenesisHash() crypto.Digest
}
// When adding new fields make sure to clear them in the roundCowState.recycle() as well to avoid dirty state
@@ -245,6 +247,10 @@ func (cb *roundCowState) BlockHdr(r basics.Round) (bookkeeping.BlockHeader, erro
return cb.lookupParent.BlockHdr(r)
}
+func (cb *roundCowState) GenesisHash() crypto.Digest {
+ return cb.lookupParent.GenesisHash()
+}
+
func (cb *roundCowState) GetStateProofVerificationContext(stateProofLastAttestedRound basics.Round) (*ledgercore.StateProofVerificationContext, error) {
return cb.lookupParent.GetStateProofVerificationContext(stateProofLastAttestedRound)
}
diff --git a/ledger/eval/cow_test.go b/ledger/eval/cow_test.go
index 225b03799..5e1253adc 100644
--- a/ledger/eval/cow_test.go
+++ b/ledger/eval/cow_test.go
@@ -24,6 +24,7 @@ import (
"github.com/stretchr/testify/require"
"github.com/algorand/go-algorand/config"
+ "github.com/algorand/go-algorand/crypto"
"github.com/algorand/go-algorand/data/basics"
"github.com/algorand/go-algorand/data/bookkeeping"
"github.com/algorand/go-algorand/data/stateproofmsg"
@@ -103,8 +104,8 @@ func (ml *mockLedger) BlockHdr(rnd basics.Round) (bookkeeping.BlockHeader, error
return bookkeeping.BlockHeader{}, errors.New("requested blockheader not found")
}
-func (ml *mockLedger) blockHdrCached(rnd basics.Round) (bookkeeping.BlockHeader, error) {
- return ml.BlockHdr(rnd)
+func (ml *mockLedger) GenesisHash() crypto.Digest {
+ panic("GenesisHash unused by tests")
}
func (ml *mockLedger) GetStateProofVerificationContext(rnd basics.Round) (*ledgercore.StateProofVerificationContext, error) {
diff --git a/ledger/eval/eval.go b/ledger/eval/eval.go
index 58f7fc8a4..714e6bddf 100644
--- a/ledger/eval/eval.go
+++ b/ledger/eval/eval.go
@@ -40,6 +40,7 @@ import (
// LedgerForCowBase represents subset of Ledger functionality needed for cow business
type LedgerForCowBase interface {
BlockHdr(basics.Round) (bookkeeping.BlockHeader, error)
+ GenesisHash() crypto.Digest
CheckDup(config.ConsensusParams, basics.Round, basics.Round, basics.Round, transactions.Txid, ledgercore.Txlease) error
LookupWithoutRewards(basics.Round, basics.Address) (ledgercore.AccountData, basics.Round, error)
LookupAsset(basics.Round, basics.Address, basics.AssetIndex) (ledgercore.AssetResource, error)
@@ -337,6 +338,10 @@ func (x *roundCowBase) BlockHdr(r basics.Round) (bookkeeping.BlockHeader, error)
return x.l.BlockHdr(r)
}
+func (x *roundCowBase) GenesisHash() crypto.Digest {
+ return x.l.GenesisHash()
+}
+
func (x *roundCowBase) GetStateProofVerificationContext(stateProofLastAttestedRound basics.Round) (*ledgercore.StateProofVerificationContext, error) {
return x.l.GetStateProofVerificationContext(stateProofLastAttestedRound)
}
diff --git a/ledger/eval/eval_test.go b/ledger/eval/eval_test.go
index b91655831..93a2afd2d 100644
--- a/ledger/eval/eval_test.go
+++ b/ledger/eval/eval_test.go
@@ -1037,6 +1037,10 @@ func (l *testCowBaseLedger) BlockHdr(basics.Round) (bookkeeping.BlockHeader, err
return bookkeeping.BlockHeader{}, errors.New("not implemented")
}
+func (l *testCowBaseLedger) GenesisHash() crypto.Digest {
+ panic("not implemented")
+}
+
func (l *testCowBaseLedger) CheckDup(config.ConsensusParams, basics.Round, basics.Round, basics.Round, transactions.Txid, ledgercore.Txlease) error {
return errors.New("not implemented")
}