summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Jannotti <jannotti@gmail.com>2024-01-05 14:21:21 -0500
committerGitHub <noreply@github.com>2024-01-05 14:21:21 -0500
commit21eec2d39b4ac93d66f9e930e7b07d45f8248c24 (patch)
tree0413392ca90833dd1287c1b1f3ddfd74463a0ef4
parente7aa0d4a785ee52f0194355912a1d9eae32a10fc (diff)
AVM: Adding sumhash and falcon_verify (#5599)
-rw-r--r--data/transactions/logic/assembler_test.go15
-rw-r--r--data/transactions/logic/crypto.go29
-rw-r--r--data/transactions/logic/crypto_test.go106
-rw-r--r--data/transactions/logic/doc.go5
-rw-r--r--data/transactions/logic/evalStateful_test.go2
-rw-r--r--data/transactions/logic/opcodes.go12
-rw-r--r--data/transactions/logic/teal.tmLanguage.json2
7 files changed, 142 insertions, 29 deletions
diff --git a/data/transactions/logic/assembler_test.go b/data/transactions/logic/assembler_test.go
index e73129b43..3f609fd7e 100644
--- a/data/transactions/logic/assembler_test.go
+++ b/data/transactions/logic/assembler_test.go
@@ -427,6 +427,13 @@ match_label1:
pushbytess "1" "2" "1"
`
+const stateProofNonsense = `
+pushbytes 0x0123456789abcd
+sumhash512
+dup; dup
+falcon_verify
+`
+
const v8Nonsense = v7Nonsense + switchNonsense + frameNonsense + matchNonsense + boxNonsense
const v9Nonsense = v8Nonsense
@@ -438,7 +445,7 @@ const spliceNonsence = `
const v10Nonsense = v9Nonsense + pairingNonsense + spliceNonsence
-const v11Nonsense = v10Nonsense
+const v11Nonsense = v10Nonsense + stateProofNonsense
const v6Compiled = "2004010002b7a60c26050242420c68656c6c6f20776f726c6421070123456789abcd208dae2087fbba51304eb02b91f656948397a7946390e8cb70fc9ea4d95f92251d047465737400320032013202320380021234292929292b0431003101310231043105310731083109310a310b310c310d310e310f3111311231133114311533000033000133000233000433000533000733000833000933000a33000b33000c33000d33000e33000f3300113300123300133300143300152d2e01022581f8acd19181cf959a1281f8acd19181cf951a81f8acd19181cf1581f8acd191810f082209240a220b230c240d250e230f2310231123122313231418191a1b1c28171615400003290349483403350222231d4a484848482b50512a632223524100034200004322602261222704634848222862482864286548482228246628226723286828692322700048482371004848361c0037001a0031183119311b311d311e311f312023221e312131223123312431253126312731283129312a312b312c312d312e312f447825225314225427042455220824564c4d4b0222382124391c0081e80780046a6f686e2281d00f23241f880003420001892224902291922494249593a0a1a2a3a4a5a6a7a8a9aaabacadae24af3a00003b003c003d816472064e014f012a57000823810858235b235a2359b03139330039b1b200b322c01a23c1001a2323c21a23c3233e233f8120af06002a494905002a49490700b400b53a03b6b7043cb8033a0c2349c42a9631007300810881088120978101c53a8101c6003a"
@@ -460,7 +467,9 @@ const spliceCompiled = "d2d3"
const v10Compiled = v9Compiled + pairingCompiled + spliceCompiled
-const V11Compiled = v10Compiled
+const stateProofCompiled = "80070123456789abcd86494985"
+
+const V11Compiled = v10Compiled + stateProofCompiled
var nonsense = map[uint64]string{
1: v1Nonsense,
@@ -541,7 +550,7 @@ func TestAssemble(t *testing.T) {
}
}
-var experiments = []uint64{}
+var experiments = []uint64{spOpcodesVersion}
// TestExperimental forces a conscious choice to promote "experimental" opcode
// groups. This will fail when we increment vFuture's LogicSigVersion. If we had
diff --git a/data/transactions/logic/crypto.go b/data/transactions/logic/crypto.go
index feb20725f..c5c39b654 100644
--- a/data/transactions/logic/crypto.go
+++ b/data/transactions/logic/crypto.go
@@ -28,6 +28,7 @@ import (
"github.com/algorand/go-algorand/crypto"
"github.com/algorand/go-algorand/crypto/secp256k1"
"github.com/algorand/go-algorand/protocol"
+ "github.com/algorand/go-sumhash"
"golang.org/x/crypto/sha3"
)
@@ -70,6 +71,34 @@ func opSHA512_256(cx *EvalContext) error {
return nil
}
+// Sumhash512 corresponds to the hash used in State Proofs
+func opSumhash512(cx *EvalContext) error {
+ last := len(cx.Stack) - 1
+ h := sumhash.New512(nil)
+ h.Write(cx.Stack[last].Bytes)
+ cx.Stack[last].Bytes = h.Sum(nil)
+ return nil
+}
+
+func opFalconVerify(cx *EvalContext) error {
+ last := len(cx.Stack) - 1 // index of PK
+ prev := last - 1 // index of signature
+ pprev := prev - 1 // index of data
+
+ var fv crypto.FalconVerifier
+ if len(cx.Stack[last].Bytes) != len(fv.PublicKey) {
+ return fmt.Errorf("invalid public key size %d != %d", len(cx.Stack[last].Bytes), len(fv.PublicKey))
+ }
+ copy(fv.PublicKey[:], cx.Stack[last].Bytes)
+
+ sig := crypto.FalconSignature(cx.Stack[prev].Bytes)
+
+ err := fv.VerifyBytes(cx.Stack[pprev].Bytes, sig)
+ cx.Stack[pprev] = boolToSV(err == nil)
+ cx.Stack = cx.Stack[:prev]
+ return nil
+}
+
// Msg is data meant to be signed and then verified with the
// ed25519verify opcode.
type Msg struct {
diff --git a/data/transactions/logic/crypto_test.go b/data/transactions/logic/crypto_test.go
index 7f539b8c7..bb6ef59c5 100644
--- a/data/transactions/logic/crypto_test.go
+++ b/data/transactions/logic/crypto_test.go
@@ -55,6 +55,31 @@ byte 0xc195eca25a6f4c82bfba0287082ddb0d602ae9230f9cf1f1a40b68f8e2c41567
testAccepts(t, progText, 1)
}
+func TestSumhash(t *testing.T) {
+ partitiontest.PartitionTest(t)
+ t.Parallel()
+
+ /* tests extracted from test vector in go-algorand/sumhash */
+ testVectors := []struct{ in, out string }{
+ {
+ "",
+ "591591c93181f8f90054d138d6fa85b63eeeb416e6fd201e8375ba05d3cb55391047b9b64e534042562cc61944930c0075f906f16710cdade381ee9dd47d10a0",
+ },
+ {
+ "a",
+ "ea067eb25622c633f5ead70ab83f1d1d76a7def8d140a587cb29068b63cb6407107aceecfdffa92579ed43db1eaa5bbeb4781223a6e07dd5b5a12d5e8bde82c6",
+ },
+ {
+ "I think, therefore I am. – Rene Descartes.",
+ "2d4583cdb18710898c78ec6d696a86cc2a8b941bb4d512f9d46d96816d95cbe3f867c9b8bd31964406c847791f5669d60b603c9c4d69dadcb87578e613b60b7a",
+ },
+ }
+
+ for _, v := range testVectors {
+ testAccepts(t, fmt.Sprintf(`byte "%s"; sumhash512; byte 0x%s; ==`, v.in, v.out), 11)
+ }
+}
+
func TestSHA3_256(t *testing.T) {
partitiontest.PartitionTest(t)
t.Parallel()
@@ -170,6 +195,14 @@ byte 0x13e49a19378bbfa8d55ac81a35b87d7bae456c79fcf04a78803d8eb45b253fab
byte 0xa2d237cd897ca70787abf04d2155c6dc2fbe26fd642e0472cd75c13dc919ef1a
ecdsa_verify Secp256r1
assert`, "int 1"},
+ {"falcon_verify", "", `
+byte 0x62fdfc072182654f163f5f0f9a621d729566c74d0aa413bf009c9800418c19cd // msg
+// public key
+byte 0xba00a5222fbaa5e2a1a61f708198a4dbc3de94b60d925042d9fa5a299ebb4be27156b1d86a174df4939342f11b776dffb8a0e874714f23318ca9acb823e9aeb14a926ed5cf76e736faa0b22e4bdedf7910decd19329f353b926ae4b404653dbc6db1885c010052b94675d4cc209ef2cf3cfe910c4ef51b6af16d8c7ab6651e57934ab19c89f771058f389ad80474740c529d59a3ea9ab9db228415fb9315dee23e8c7229398c4b0a2b7c5d6eff6e7d8cf1a776ae37f6272082796c0b2a0af637f7ce8fa7f1675dfbd1766543cbf3f19544d635298ea1fafe96ad1bb06fcc6ae9ff9c34acacb88653555c37f2ad6c4eb408478b0d2b6269841243f29b18fa8e0d5050f4f93878e53aac466dc4eb5a7194cb2213c26a2b8c7ccea06f89af26ae85315454da1b15952be639bb94fe3e99236291c4a1edfbe9faf8f32589bf47eb536b28e2cfbdea799d9cf4c88ef85ae45d451e1ab3431c247b796cbf12e63b737cc4894ad7a204f680a449cbbd2e86deca1069b3592977bd8ac7c5b5e1c1b436cde65177b6e82b2e666117a8e37b58122d1a31307ca112311e665b32c68bd42531b4e6bc79957d3d865f6470b8213db8175e5c7115f4ad520a4711b12d9004e661346c4da4cb3e95954ac58e075a320b862a6a317e0988d8fc376fb14562773b9d35d5a44ba951d866a3a06ac93a55e1a26fa91718db49a53e78d9e61d6120dfadd2b4929579ac56ccaac0f8e704826b55b4ca6d8020e42a6e62b5e41708e2e6848cd047385fa1df4f51733df35dbee25c96c4176eae332ca4df31c695fff8be31b4be62e63c3e049483c89384fb1d802e58db5514a59eb96e527b202d0cf45dc760fa0439afbc661868b9408e67254c8cf7c689c50d2f29bccd59c71ea7b6dd368de68669fdf889ac1f8cd390ea17894dd0538ff6e7c740bbf03b4fe32ad66c483c823548eea84f85826da44016bd8cdf2315b07a96a9737ebc7cb244547be3f759bdf50b467552c58333ed7e61cde799346bccc29d5d377d9d5364c369ffd88a83f90a699b3622184436b518e9196524ac9b55385b39ec099d9c18386e06b9dcad2499ddb9673cb87c652209ee60511c9249f1b7ab2b948b5e8b9115c218d5b793d65b96e2fc9e2c6c40ba63791bb89d7d96c33536ad7e6668a85e52ec7e1450a69f25766deeaeb41bcd249394b8ab65a286312db461c363cebe431c4dd5fd3b6bb5d26ae2c597799f400abb3ba160522e2e6da5ebd170a45c9ce80b135a5b330656aab26399bcacd857a7f237dfd2b14ecbfbcaabc7291ba78fe19ac2ecf005b66bb9771bf64f090269a2341967e79702733dc617b469ac12123faeb4c70d6fffac25f9fcd7dbd12ca363985b9bd845e939e6caf328e2bf8e53725bae94fbe30bfdbbc21e584ba72d7badbc2a0915c9faf9c69ad3703cf99a16399b38df157be8ec3a78f20d24b2131f9c25b3c1da70fc6c0c7aa9e9da3108368ca6211dcfa4988b1ace3c28b15b0559224570fbe3cde364734c7a66a0525c1d41e26788cd1c8a3888f344c9385804364f8430ca7d22338cc941917da3dc47a00aae13e3e972af49940c8fa179574694e369a3d5e67db6c91bf843151ca0fff512d9c322c690063ae9bd671815e9d03b3a841952ce04683509e415b8d5aebfcdbd6bd55efbffb2463cf2b96ccb8650a6cee732c8d4ce6409b9a747317866759553f1c5bcc392c98d14a034ccaaa6df5723bb88c38e80
+// sig
+byte 0x0a85ea3bb342a95a3941a4c2280c686729c76bc164092c0e203388460c556273e6f0a92640650c37e9d5b08fbd8d6bcca940acac9964e64a9e78bd28086b52898812264985e19c3d26318be2ec8852ca2ae2380746428cd08124cf792790d127d3dad09fe891cbadefef36269ae7d584b77ec428d794a6c3b7555956db00314d14a0aa14936830c8622623916639743b218243344224472240cfd158819190ede108394063c3df9c474eb16aa750e48663515d8229d3849670e30891142b632a6a282d915273a5f219d65ebe6b9e6c88170ac62c16a44895a950bfec82819221dab1358861bf0aa6b6342477016d50502a298840ddc42b3ade784b643c63c5e47993ada37dfdc0d56a1c7e4690b5a1d6485900b84f0b61425383b14d4b7ccc0abe8284a47a6f22050838b0482ad8ad389151c25e790ad670d5530f9b3dc518bb0a410f64346a74dc824238026daaa4ad97518d93670a48cf8f86ece593d23ab3a0d601d49a975db291f0d76263551e9f0b8a1b42396a27d9a122210330c692d5545d67c808b50560fc3d4933fa70c463513d7183e8aa091f34dd4426272620fe4b357deea710c687bb7a475d0ed0a40a26ae8f2a357e7a8fa5d5434050c1a36beaa7a90ee4db213a126db8151f2f4bbb4889d4e42bbd19f62dd7285def148071fb7f4f16b28c1d145d2e621fee275161a3d5b9319e7a59527c3d5c2838ef503e4166f2c22118b22bf80e8a1fc1bbbba00f231d2b1a8d3e592bdcc5fd40a2ecebb5ad27a51e7867715b54185a3e62951a5d808d80c31a59e6a3ca53a51eadc34c76dfd6aac22a6e805163b5e9ac8090869a9cd1e2972af7192bcd1da39c30f423ebc86d1976e8f52052262521d3b8ae7eb99d0ad623d811bac636f447e7dc9dcef6f52befd95861f1917116517b0e9b56a85967ab701ff8f1d4de443efce1b2a3d85b592df7a8c87814e8981575ef4e72757c5afa6bec4358e2f29966ad2830e4782f9a293351dfcaac1d0ca30ec1b5fd08a40a6e82938427a68641b96252a85443141c081982ba4d3c8ab05a1a545ea49c23ee07643ec5f013c2676db09cb834ef61817e615ad19c5829216026e5635dc13cad5ffb8bc267bf58d4ebbf100c3045e250c02c10772e96c580db049c80fdd3188e19ad893d16ac100052c557378416929319c9c262c21b768e6058a09b4e4800ae624c892117ec71504a283f558c623a212d048d5d401b00448b18ac25e1c99ab35d91f78badebcd651e86f3465ef99a0afa1721d2153e4a7b51d22b344a8dd102e7411abfe4bd5b8e2d62015edc08fc461fa90cfa666a9a42a0a86e11d6988913ba0259096cb846a1fd311c4cb693c4e3e1ed2ab57e2a5e0bd4616a79e22b28caa6d10dd09225e44bbdbfa1b7b23887055a90918220252777d5a620351cb013cc28346fc69d348165a39d03243a84a9c9bcd4d557a8e9607256baab893a0a5644520686be935e9ead84501f743a489a431cf10b8c27d3901c87b8771ce65e3130a7fe6ad62b709c23bbef1381b1ed49222f487db16af3c9d6779c01c986ea9f823be017fb8bce8e00f2b32840d54e8f656139a4c492257ee8743a8c5f51450c0366655e2b02d27619d07e556001430b04454891247813c8bc31bdee926d039a5038bfca8dc35e57789950442ad7ab3cfc031a8354bd9c462a37052d0b62066bcee0c292b890a71f4ea65895a7d837283404842c59f08414b20ec1b4fda6cc0c4d62216e8ead74ba90196168bc449a2050b442181ea57b915581bc387ed412e4cd5970fd0fb83c94fbbf960d05ffe6d0a26171c249809604a0b2b411e2d6622145c936e31258baf2b7d3c413a9a1d67bc4026d01b47a10b6c5b87f6a36ba1cedd681ca55b9c042bf9afcfcb636040793e08158dd877c49c16658f819129e26237427a1d80b941fbabb4abd4f1da0b6d428a59fbc450620eeb1651849e5972fb12e6dc8092a9fda70206a48d9dc2645641a147626350cf45b1a7d57724fcab0a594df7c023928a3c7a2fc3c9d33e9af10ae5ed282c475a611671d20d90752f2a28db48b7e5d9184212432fa948fbc885f866c93a0b7f510329aea4d53ecf9482f42974beaf289086afdb4797aa129d10639948f46a805ea4000cf1554505f4bd9d775d5894da115f5840913d5070c860b3a623eb261f5f928a31cbcec17c4274b5d1b28fdb231cc8f606c9dc324db5c12f97518fd03466541f7881762c25d711976c6d4f9271d29fa51dc263f650a32010343a51e7dab344e2f6d768864072ddb5df58486434998a280aad94886ea7a11132184e6274d4cd59a5deabf8a4dbbe29e9c234a52d3972608d0a3ea92a78e08531bb938384444246be5bc594ed4d06168e870924e8913f8242bd35f7c9d5ee238cb6db17496047acce0183f2d10a4cf2bbc8e39daf44e630393a0473b8983863b1998c17026ff35ec32a8058fd603ec369b80a94cb7b555cb469f6468de3909b21293b8d0a53a5c813d218d7c630f4d47bb1eb88253e6e1af721ba8a4453e
+falcon_verify
+assert`, "int 1"},
{"vrf_verify", "", `byte 0x72
byte 0xae5b66bdf04b4c010bfe32b2fc126ead2107b697634f6f7337b9bff8785ee111200095ece87dde4dbe87343f6df3b107d91798c8a7eb1245d3bb9c5aafb093358c13e6ae1111a55717e895fd15f99f07
byte 0x3d4017c3e843895a92b70aa74d1b7ebc9c982ccf2ec4968cc0cd55f12af4660c
@@ -264,6 +297,52 @@ func TestEd25519VerifyBare(t *testing.T) {
}
}
+func TestFalconVerify(t *testing.T) {
+ partitiontest.PartitionTest(t)
+ t.Parallel()
+
+ var s crypto.FalconSeed
+ fs, err := crypto.GenerateFalconSigner(s)
+ require.NoError(t, err)
+
+ msg := "62fdfc072182654f163f5f0f9a621d729566c74d0aa413bf009c9800418c19cd"
+ data, err := hex.DecodeString(msg)
+ require.NoError(t, err)
+
+ yes := testProg(t, fmt.Sprintf(`arg 0; arg 1; byte 0x%s; falcon_verify`,
+ hex.EncodeToString(fs.PublicKey[:])), 11)
+ require.NoError(t, err)
+ no := testProg(t, fmt.Sprintf(`arg 0; arg 1; byte 0x%s; falcon_verify; !`,
+ hex.EncodeToString(fs.PublicKey[:])), 11)
+ require.NoError(t, err)
+
+ for v := uint64(11); v <= AssemblerMaxVersion; v++ {
+ t.Run(fmt.Sprintf("v=%d", v), func(t *testing.T) {
+ yes.Program[0] = byte(v)
+ sig, err := fs.SignBytes(data)
+ require.NoError(t, err)
+
+ var txn transactions.SignedTxn
+ txn.Lsig.Args = [][]byte{data[:], sig[:]}
+ testLogicBytes(t, yes.Program, defaultSigParams(txn))
+ testLogicBytes(t, no.Program, defaultSigParams(txn), "REJECT")
+
+ // short sig will fail
+ txn.Lsig.Args[1] = sig[1:]
+ testLogicBytes(t, yes.Program, defaultSigParams(txn), "REJECT")
+ testLogicBytes(t, no.Program, defaultSigParams(txn))
+
+ // flip a bit and it should not pass
+ msg1 := "52fdfc072182654f163f5f0f9a621d729566c74d0aa413bf009c9800418c19cd"
+ data1, err := hex.DecodeString(msg1)
+ require.NoError(t, err)
+ txn.Lsig.Args = [][]byte{data1, sig[:]}
+ testLogicBytes(t, yes.Program, defaultSigParams(txn), "REJECT")
+ testLogicBytes(t, no.Program, defaultSigParams(txn))
+ })
+ }
+}
+
func keyToByte(tb testing.TB, b *big.Int) []byte {
k := make([]byte, 32)
require.NotPanics(tb, func() {
@@ -636,26 +715,13 @@ int ` + fmt.Sprintf("%d", testLogicBudget-2500-8) + `
testAccepts(t, source, fidoVersion)
}
-func BenchmarkHash(b *testing.B) {
- for _, hash := range []string{"sha256", "keccak256", "sha512_256"} {
- b.Run(hash+"-0w", func(b *testing.B) { // hash 0 bytes
- benchmarkOperation(b, "", "byte 0x; "+hash+"; pop", "int 1")
- })
- b.Run(hash+"-32", func(b *testing.B) { // hash 32 bytes
- benchmarkOperation(b, "int 32; bzero", hash, "pop; int 1")
- })
- b.Run(hash+"-128", func(b *testing.B) { // hash 128 bytes
- benchmarkOperation(b, "int 32; bzero",
- "dup; concat; dup; concat;"+hash, "pop; int 1")
- })
- b.Run(hash+"-512", func(b *testing.B) { // hash 512 bytes
- benchmarkOperation(b, "int 32; bzero",
- "dup; concat; dup; concat; dup; concat; dup; concat;"+hash, "pop; int 1")
- })
- b.Run(hash+"-4096", func(b *testing.B) { // hash 4k bytes
- benchmarkOperation(b, "int 32; bzero",
- "dup; concat; dup; concat; dup; concat; dup; concat; dup; concat; dup; concat; dup; concat;"+hash, "pop; int 1")
- })
+func BenchmarkHashes(b *testing.B) {
+ for _, hash := range []string{"sha256", "keccak256" /* skip, same as keccak "sha3_256", */, "sha512_256", "sumhash512"} {
+ for _, size := range []int{0, 32, 128, 512, 1024, 4096} {
+ b.Run(hash+"-"+strconv.Itoa(size), func(b *testing.B) {
+ benchmarkOperation(b, "", fmt.Sprintf("int %d; bzero; %s; pop", size, hash), "int 1")
+ })
+ }
}
}
diff --git a/data/transactions/logic/doc.go b/data/transactions/logic/doc.go
index cfaadebdf..fde870a9d 100644
--- a/data/transactions/logic/doc.go
+++ b/data/transactions/logic/doc.go
@@ -38,6 +38,9 @@ var opDescByName = map[string]OpDesc{
"sha512_256": {"SHA512_256 hash of value A, yields [32]byte", "", nil},
"sha3_256": {"SHA3_256 hash of value A, yields [32]byte", "", nil},
+ "sumhash512": {"sumhash512 of value A, yields [64]byte", "", nil},
+ "falcon_verify": {"for (data A, compressed-format signature B, pubkey C) verify the signature of data against the pubkey", "", nil},
+
"ed25519verify": {"for (data A, signature B, pubkey C) verify the signature of (\"ProgData\" || program_hash || data) against the pubkey => {0 or 1}", "The 32 byte public key is the last element on the stack, preceded by the 64 byte signature at the second-to-last element on the stack, preceded by the data which was signed at the third-to-last element on the stack.", nil},
"ed25519verify_bare": {"for (data A, signature B, pubkey C) verify the signature of the data against the pubkey => {0 or 1}", "", nil},
"ecdsa_verify": {"for (data A, signature B, C and pubkey D, E) verify the signature of the data against the pubkey => {0 or 1}", "The 32 byte Y-component of a public key is the last element on the stack, preceded by X-component of a pubkey, preceded by S and R components of a signature, preceded by the data that is fifth element on the stack. All values are big-endian encoded. The signed data must be 32 bytes long, and signatures in lower-S form are only accepted.", []string{"curve index"}},
@@ -349,7 +352,7 @@ var OpGroups = map[string][]string{
"Byte Array Manipulation": {"getbit", "setbit", "getbyte", "setbyte", "concat", "len", "substring", "substring3", "extract", "extract3", "extract_uint16", "extract_uint32", "extract_uint64", "replace2", "replace3", "base64_decode", "json_ref"},
"Byte Array Arithmetic": {"b+", "b-", "b/", "b*", "b<", "b>", "b<=", "b>=", "b==", "b!=", "b%", "bsqrt"},
"Byte Array Logic": {"b|", "b&", "b^", "b~"},
- "Cryptography": {"sha256", "keccak256", "sha512_256", "sha3_256", "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"},
+ "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"},
diff --git a/data/transactions/logic/evalStateful_test.go b/data/transactions/logic/evalStateful_test.go
index b0c6196e3..fe30d2594 100644
--- a/data/transactions/logic/evalStateful_test.go
+++ b/data/transactions/logic/evalStateful_test.go
@@ -3098,6 +3098,8 @@ func TestReturnTypes(t *testing.T) {
"err": true,
"return": true,
+ // these have unusual input size requirements not encoded in proto
+ "falcon_verify": true,
"ecdsa_pk_decompress": true,
"frame_dig": true, // would need a "proto" subroutine
diff --git a/data/transactions/logic/opcodes.go b/data/transactions/logic/opcodes.go
index 650f26ed9..18af2af1b 100644
--- a/data/transactions/logic/opcodes.go
+++ b/data/transactions/logic/opcodes.go
@@ -77,6 +77,8 @@ 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 spOpcodesVersion = 11 // falcon_verify, sumhash512
+
// Unlimited Global Storage opcodes
const boxVersion = 8 // box_*
@@ -503,9 +505,9 @@ var OpSpecs = []OpSpec{
is currently a useful pattern that requires hashes on long slices to
creating logicsigs in apps.
- {0x01, "sha256", opSHA256, proto("b:b"), unlimitedStorage, costByLength(12, 6, 8)},
- {0x02, "keccak256", opKeccak256, proto("b:b"), unlimitedStorage, costByLength(58, 4, 8)},
- {0x03, "sha512_256", opSHA512_256, proto("b:b"), 7, unlimitedStorage, costByLength(17, 5, 8)},
+ {0x01, "sha256", opSHA256, proto("b:b"), ?, costByLength(...)},
+ {0x02, "keccak256", opKeccak256, proto("b:b"), ?, costByLength(...)},
+ {0x03, "sha512_256", opSHA512_256, proto("b:b"), ?, costByLength(...)},
*/
{0x04, "ed25519verify", opEd25519Verify, proto("b63:T"), 1, costly(1900).only(ModeSig)},
@@ -647,6 +649,8 @@ var OpSpecs = []OpSpec{
{0x83, "pushints", opPushInts, proto(":", "", "[N items]").stackExplain(opPushIntsStackChange), 8, constants(asmPushInts, checkIntImmArgs, "uint ...", immInts).typed(typePushInts).trust()},
{0x84, "ed25519verify_bare", opEd25519VerifyBare, proto("b63:T"), 7, costly(1900)},
+ {0x85, "falcon_verify", opFalconVerify, proto("bbb:T"), spOpcodesVersion, costly(1700)}, // dynamic for internal hash?
+ {0x86, "sumhash512", opSumhash512, proto("b:6"), spOpcodesVersion, costByLength(150, 7, 4, 0)},
// "Function oriented"
{0x88, "callsub", opCallSub, proto(":"), 4, detBranch()},
@@ -669,7 +673,7 @@ var OpSpecs = []OpSpec{
{0x97, "divw", opDivw, proto("iii:i"), 6, detDefault()},
{0x98, "sha3_256", opSHA3_256, proto("b:b"), 7, costly(130)},
/* Will end up following keccak256 -
- {0x98, "sha3_256", opSHA3_256, proto("b:b"), unlimitedStorage, costByLength(58, 4, 8)},},
+ {0x98, "sha3_256", opSHA3_256, proto("b:b"), ?, costByLength(...)},},
*/
// Byteslice math.
diff --git a/data/transactions/logic/teal.tmLanguage.json b/data/transactions/logic/teal.tmLanguage.json
index e414922e8..915957f7f 100644
--- a/data/transactions/logic/teal.tmLanguage.json
+++ b/data/transactions/logic/teal.tmLanguage.json
@@ -76,7 +76,7 @@
},
{
"name": "keyword.operator.teal",
- "match": "^(\\!|\\!\\=|%|\u0026|\u0026\u0026|\\*|\\+|\\-|/|\\\u003c|\\\u003c\\=|\\=\\=|\\\u003e|\\\u003e\\=|\\^|addw|bitlen|btoi|divmodw|divw|exp|expw|itob|mulw|shl|shr|sqrt|\\||\\|\\||\\~|b\\!\\=|b%|b\\*|b\\+|b\\-|b/|b\\\u003c|b\\\u003c\\=|b\\=\\=|b\\\u003e|b\\\u003e\\=|bsqrt|b\u0026|b\\^|b\\||b\\~|base64_decode|concat|extract|extract3|extract_uint16|extract_uint32|extract_uint64|getbit|getbyte|json_ref|len|replace2|replace3|setbit|setbyte|substring|substring3|ec_add|ec_map_to|ec_multi_scalar_mul|ec_pairing_check|ec_scalar_mul|ec_subgroup_check|ecdsa_pk_decompress|ecdsa_pk_recover|ecdsa_verify|ed25519verify|ed25519verify_bare|keccak256|sha256|sha3_256|sha512_256|vrf_verify|gitxn|gitxna|gitxnas|itxn|itxn_begin|itxn_field|itxn_next|itxn_submit|itxna|itxnas)\\b"
+ "match": "^(\\!|\\!\\=|%|\u0026|\u0026\u0026|\\*|\\+|\\-|/|\\\u003c|\\\u003c\\=|\\=\\=|\\\u003e|\\\u003e\\=|\\^|addw|bitlen|btoi|divmodw|divw|exp|expw|itob|mulw|shl|shr|sqrt|\\||\\|\\||\\~|b\\!\\=|b%|b\\*|b\\+|b\\-|b/|b\\\u003c|b\\\u003c\\=|b\\=\\=|b\\\u003e|b\\\u003e\\=|bsqrt|b\u0026|b\\^|b\\||b\\~|base64_decode|concat|extract|extract3|extract_uint16|extract_uint32|extract_uint64|getbit|getbyte|json_ref|len|replace2|replace3|setbit|setbyte|substring|substring3|ec_add|ec_map_to|ec_multi_scalar_mul|ec_pairing_check|ec_scalar_mul|ec_subgroup_check|ecdsa_pk_decompress|ecdsa_pk_recover|ecdsa_verify|ed25519verify|ed25519verify_bare|falcon_verify|keccak256|sha256|sha3_256|sha512_256|sumhash512|vrf_verify|gitxn|gitxna|gitxnas|itxn|itxn_begin|itxn_field|itxn_next|itxn_submit|itxna|itxnas)\\b"
}
]
},