diff --git a/data/transactions/logic/README.md b/data/transactions/logic/README.md index ca5e04bef4..269832d38a 100644 --- a/data/transactions/logic/README.md +++ b/data/transactions/logic/README.md @@ -137,14 +137,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 @@ -463,8 +467,6 @@ these results may contain leading zero bytes. | `keccak256` | Keccak256 hash of value A, yields [32]byte | | `sha512_256` | SHA512_256 hash of value A, yields [32]byte | | `sha3_256` | SHA3_256 hash of value A, yields [32]byte | -| `sumhash512` | sumhash512 of value A, yields [64]byte | -| `falcon_verify` | for (data A, compressed-format signature B, pubkey C) verify the signature of data against the pubkey | | `ed25519verify` | for (data A, signature B, pubkey C) verify the signature of ("ProgData" \|\| program_hash \|\| data) against the pubkey => {0 or 1} | | `ed25519verify_bare` | for (data A, signature B, pubkey C) verify the signature of the data against the pubkey => {0 or 1} | | `ecdsa_verify v` | for (data A, signature B, C and pubkey D, E) verify the signature of the data against the pubkey => {0 or 1} | diff --git a/data/transactions/logic/README_in.md b/data/transactions/logic/README_in.md index 31f8fb05be..848c345f97 100644 --- a/data/transactions/logic/README_in.md +++ b/data/transactions/logic/README_in.md @@ -123,14 +123,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 diff --git a/data/transactions/logic/TEAL_opcodes_v11.md b/data/transactions/logic/TEAL_opcodes_v11.md index 08a4b3ee5a..8bbad2e206 100644 --- a/data/transactions/logic/TEAL_opcodes_v11.md +++ b/data/transactions/logic/TEAL_opcodes_v11.md @@ -1177,22 +1177,6 @@ pushints args are not added to the intcblock during assembly processes - **Cost**: 1900 - Availability: v7 -## falcon_verify - -- Bytecode: 0x85 -- Stack: ..., A: []byte, B: [1232]byte, C: [1793]byte → ..., bool -- for (data A, compressed-format signature B, pubkey C) verify the signature of data against the pubkey -- **Cost**: 1700 -- Availability: v11 - -## sumhash512 - -- Bytecode: 0x86 -- Stack: ..., A: []byte → ..., [64]byte -- sumhash512 of value A, yields [64]byte -- **Cost**: 150 + 7 per 4 bytes of A -- Availability: v11 - ## callsub - Syntax: `callsub TARGET` where TARGET: branch offset diff --git a/data/transactions/logic/assembler_test.go b/data/transactions/logic/assembler_test.go index 34b2ed1995..093fe7de3d 100644 --- a/data/transactions/logic/assembler_test.go +++ b/data/transactions/logic/assembler_test.go @@ -455,7 +455,9 @@ const spliceNonsence = ` const v10Nonsense = v9Nonsense + pairingNonsense + spliceNonsence -const v11Nonsense = v10Nonsense + incentiveNonsense + stateProofNonsense + mimcNonsense +const v11Nonsense = v10Nonsense + incentiveNonsense + mimcNonsense + +const v12Nonsense = v11Nonsense + stateProofNonsense const v6Compiled = "2004010002b7a60c26050242420c68656c6c6f20776f726c6421070123456789abcd208dae2087fbba51304eb02b91f656948397a7946390e8cb70fc9ea4d95f92251d047465737400320032013202320380021234292929292b0431003101310231043105310731083109310a310b310c310d310e310f3111311231133114311533000033000133000233000433000533000733000833000933000a33000b33000c33000d33000e33000f3300113300123300133300143300152d2e01022581f8acd19181cf959a1281f8acd19181cf951a81f8acd19181cf1581f8acd191810f082209240a220b230c240d250e230f2310231123122313231418191a1b1c28171615400003290349483403350222231d4a484848482b50512a632223524100034200004322602261222704634848222862482864286548482228246628226723286828692322700048482371004848361c0037001a0031183119311b311d311e311f312023221e312131223123312431253126312731283129312a312b312c312d312e312f447825225314225427042455220824564c4d4b0222382124391c0081e80780046a6f686e2281d00f23241f880003420001892224902291922494249593a0a1a2a3a4a5a6a7a8a9aaabacadae24af3a00003b003c003d816472064e014f012a57000823810858235b235a2359b03139330039b1b200b322c01a23c1001a2323c21a23c3233e233f8120af06002a494905002a49490700b400b53a03b6b7043cb8033a0c2349c42a9631007300810881088120978101c53a8101c6003a" @@ -482,7 +484,8 @@ const incentiveCompiled = "757401" const stateProofCompiled = "80070123456789abcd86494985" const mimcCompiled = "802011223344556677889900aabbccddeeff11223344556677889900aabbccddeeffe601" -const V11Compiled = v10Compiled + incentiveCompiled + stateProofCompiled + mimcCompiled +const v11Compiled = v10Compiled + incentiveCompiled + mimcCompiled +const v12Compiled = v11Compiled + stateProofCompiled var nonsense = map[uint64]string{ 1: v1Nonsense, @@ -496,6 +499,7 @@ var nonsense = map[uint64]string{ 9: v9Nonsense, 10: v10Nonsense, 11: v11Nonsense, + 12: v12Nonsense, } var compiled = map[uint64]string{ @@ -509,7 +513,8 @@ var compiled = map[uint64]string{ 8: "08" + v8Compiled, 9: "09" + v9Compiled, 10: "0a" + v10Compiled, - 11: "0b" + V11Compiled, + 11: "0b" + v11Compiled, + 12: "0c" + v12Compiled, } func pseudoOp(opcode string) bool { diff --git a/data/transactions/logic/crypto_test.go b/data/transactions/logic/crypto_test.go index 5c14e23049..8713823747 100644 --- a/data/transactions/logic/crypto_test.go +++ b/data/transactions/logic/crypto_test.go @@ -76,7 +76,7 @@ func TestSumhash(t *testing.T) { } for _, v := range testVectors { - testAccepts(t, fmt.Sprintf(`byte "%s"; sumhash512; byte 0x%s; ==`, v.in, v.out), 11) + testAccepts(t, fmt.Sprintf(`byte "%s"; sumhash512; byte 0x%s; ==`, v.in, v.out), 12) } } @@ -390,13 +390,13 @@ func TestFalconVerify(t *testing.T) { require.NoError(t, err) yes := testProg(t, fmt.Sprintf(`arg 0; arg 1; byte 0x%s; falcon_verify`, - hex.EncodeToString(fs.PublicKey[:])), 11) + hex.EncodeToString(fs.PublicKey[:])), 12) require.NoError(t, err) no := testProg(t, fmt.Sprintf(`arg 0; arg 1; byte 0x%s; falcon_verify; !`, - hex.EncodeToString(fs.PublicKey[:])), 11) + hex.EncodeToString(fs.PublicKey[:])), 12) require.NoError(t, err) - for v := uint64(11); v <= AssemblerMaxVersion; v++ { + for v := uint64(12); v <= AssemblerMaxVersion; v++ { t.Run(fmt.Sprintf("v=%d", v), func(t *testing.T) { yes.Program[0] = byte(v) sig, err := fs.SignBytes(data) diff --git a/data/transactions/logic/eval_test.go b/data/transactions/logic/eval_test.go index 27a64f1b82..e6f0abe320 100644 --- a/data/transactions/logic/eval_test.go +++ b/data/transactions/logic/eval_test.go @@ -1266,6 +1266,8 @@ global PayoutsPercent; int 4; ==; assert global PayoutsMinBalance; int 5; ==; assert global PayoutsMaxBalance; int 6; ==; assert ` +const globalV12TestProgram = globalV11TestProgram + ` +` func TestAllGlobals(t *testing.T) { partitiontest.PartitionTest(t) @@ -1289,6 +1291,7 @@ func TestAllGlobals(t *testing.T) { 9: {CallerApplicationAddress, globalV9TestProgram}, 10: {GenesisHash, globalV10TestProgram}, 11: {PayoutsMaxBalance, globalV11TestProgram}, + 12: {PayoutsMaxBalance, globalV12TestProgram}, } // tests keys are versions so they must be in a range 1..AssemblerMaxVersion plus zero version require.LessOrEqual(t, len(tests), AssemblerMaxVersion+1) @@ -1800,6 +1803,11 @@ assert int 1 ` +const testTxnProgramTextV12 = testTxnProgramTextV11 + ` +assert +int 1 +` + func makeSampleTxn() transactions.SignedTxn { var txn transactions.SignedTxn copy(txn.Txn.Sender[:], []byte("aoeuiaoeuiaoeuiaoeuiaoeuiaoeui00")) @@ -1914,6 +1922,7 @@ func TestTxn(t *testing.T) { 9: testTxnProgramTextV9, 10: testTxnProgramTextV10, 11: testTxnProgramTextV11, + 12: testTxnProgramTextV12, } for i, txnField := range TxnFieldNames { diff --git a/data/transactions/logic/langspec_v11.json b/data/transactions/logic/langspec_v11.json index cb054ebcd8..58d5657253 100644 --- a/data/transactions/logic/langspec_v11.json +++ b/data/transactions/logic/langspec_v11.json @@ -3072,42 +3072,6 @@ "Cryptography" ] }, - { - "Opcode": 133, - "Name": "falcon_verify", - "Args": [ - "[]byte", - "[1232]byte", - "[1793]byte" - ], - "Returns": [ - "bool" - ], - "Size": 1, - "DocCost": "1700", - "Doc": "for (data A, compressed-format signature B, pubkey C) verify the signature of data against the pubkey", - "IntroducedVersion": 11, - "Groups": [ - "Cryptography" - ] - }, - { - "Opcode": 134, - "Name": "sumhash512", - "Args": [ - "[]byte" - ], - "Returns": [ - "[64]byte" - ], - "Size": 1, - "DocCost": "150 + 7 per 4 bytes of A", - "Doc": "sumhash512 of value A, yields [64]byte", - "IntroducedVersion": 11, - "Groups": [ - "Cryptography" - ] - }, { "Opcode": 136, "Name": "callsub", diff --git a/data/transactions/logic/opcodes.go b/data/transactions/logic/opcodes.go index b283c49656..a8de92ce8d 100644 --- a/data/transactions/logic/opcodes.go +++ b/data/transactions/logic/opcodes.go @@ -28,7 +28,7 @@ import ( ) // LogicVersion defines default assembler and max eval versions -const LogicVersion = 11 +const LogicVersion = 12 // rekeyingEnabledVersion is the version of TEAL where RekeyTo functionality // was enabled. This is important to remember so that old TEAL accounts cannot @@ -75,13 +75,13 @@ const sharedResourcesVersion = 9 // apps can access resources from other transac const pairingVersion = 10 // bn256 opcodes. will add bls12-381, and unify the available opcodes. const spliceVersion = 10 // box splicing/resizing +const incentiveVersion = 11 // block fields, heartbeat +const mimcVersion = 11 + // EXPERIMENTAL. These should be revisited whenever a new LogicSigVersion is // moved from vFuture to a new consensus version. If they remain unready, bump // their version, and fixup TestAssemble() in assembler_test.go. -const incentiveVersion = 11 // block fields, heartbeat - -const spOpcodesVersion = 11 // falcon_verify, sumhash512 -const mimcVersion = 11 +const spOpcodesVersion = 12 // falcon_verify, sumhash512 // Unlimited Global Storage opcodes const boxVersion = 8 // box_* diff --git a/ledger/simulation/simulation_eval_test.go b/ledger/simulation/simulation_eval_test.go index ef81a8a10e..c36171eae6 100644 --- a/ledger/simulation/simulation_eval_test.go +++ b/ledger/simulation/simulation_eval_test.go @@ -6961,6 +6961,9 @@ func TestUnnamedResources(t *testing.T) { env.OptIntoApp(otherAppUser, otherAppID) proto := env.TxnInfo.CurrentProtocolParams() + if v > int(proto.LogicSigVersion) { + t.Skip("not testing in unsupported proto") + } expectedUnnamedResourceGroupAssignment := &simulation.ResourceTracker{ MaxAccounts: proto.MaxTxGroupSize * (proto.MaxAppTxnAccounts + proto.MaxAppTxnForeignApps), MaxAssets: proto.MaxTxGroupSize * proto.MaxAppTxnForeignAssets, @@ -7196,6 +7199,11 @@ func TestUnnamedResourcesAccountLocalWrite(t *testing.T) { sender := env.Accounts[0] testAppUser := env.Accounts[1].Addr + proto := env.TxnInfo.CurrentProtocolParams() + if v > int(proto.LogicSigVersion) { + t.Skip("not testing in unsupported proto") + } + program := fmt.Sprintf(`#pragma version %d txn ApplicationID ! @@ -7232,7 +7240,6 @@ int 1 }) stxn := txn.Txn().Sign(sender.Sk) - proto := env.TxnInfo.CurrentProtocolParams() expectedUnnamedResourceAssignment := &simulation.ResourceTracker{ MaxAccounts: proto.MaxTxGroupSize * (proto.MaxAppTxnAccounts + proto.MaxAppTxnForeignApps), MaxAssets: proto.MaxTxGroupSize * proto.MaxAppTxnForeignAssets, @@ -7338,6 +7345,11 @@ func TestUnnamedResourcesCreatedAppsAndAssets(t *testing.T) { t.Run(fmt.Sprintf("v%d", v), func(t *testing.T) { t.Parallel() simulationTest(t, func(env simulationtesting.Environment) simulationTestCase { + proto := env.TxnInfo.CurrentProtocolParams() + if v > int(proto.LogicSigVersion) { + t.Skip("not testing in unsupported proto") + } + sender := env.Accounts[0] otherResourceCreator := env.Accounts[1] otherAccount := env.Accounts[2].Addr @@ -7435,7 +7447,6 @@ int 1 appCreateStxn := appCreateTxn.Txn().Sign(otherResourceCreator.Sk) appCallStxn := appCallTxn.Txn().Sign(sender.Sk) - proto := env.TxnInfo.CurrentProtocolParams() expectedUnnamedResourceAssignment := simulation.ResourceTracker{ MaxAccounts: (proto.MaxTxGroupSize - 1) * (proto.MaxAppTxnAccounts + proto.MaxAppTxnForeignApps), MaxAssets: (proto.MaxTxGroupSize - 1) * proto.MaxAppTxnForeignAssets, @@ -7702,6 +7713,11 @@ func TestUnnamedResourcesBoxIOBudget(t *testing.T) { env := simulationtesting.PrepareSimulatorTest(t) defer env.Close() + proto := env.TxnInfo.CurrentProtocolParams() + if v > int(proto.LogicSigVersion) { + t.Skip("not testing in unsupported proto") + } + sender := env.Accounts[0] appID := env.CreateApp(sender.Addr, simulationtesting.AppParams{ @@ -7709,8 +7725,6 @@ func TestUnnamedResourcesBoxIOBudget(t *testing.T) { ClearStateProgram: fmt.Sprintf("#pragma version %d\n int 1", v), }) - proto := env.TxnInfo.CurrentProtocolParams() - // MBR is needed for boxes. transferable := env.Accounts[1].AcctData.MicroAlgos.Raw - proto.MinBalance - proto.MinTxnFee env.TransferAlgos(env.Accounts[1].Addr, appID.Address(), transferable) @@ -8587,6 +8601,10 @@ func TestUnnamedResourcesLimits(t *testing.T) { defer env.Close() proto := env.TxnInfo.CurrentProtocolParams() + if v > int(proto.LogicSigVersion) { + t.Skip("not testing in unsupported proto") + return + } sender := env.Accounts[0] otherAccounts := make([]basics.Address, len(env.Accounts)-1) @@ -8753,6 +8771,10 @@ func TestUnnamedResourcesCrossProductLimits(t *testing.T) { defer env.Close() proto := env.TxnInfo.CurrentProtocolParams() + if v > int(proto.LogicSigVersion) { + t.Skip("not testing in unsupported proto") + return + } sender := env.Accounts[0] otherAccounts := make([]basics.Address, proto.MaxTxGroupSize)