From bf4dc8f7593571e8c47d975467b3ee12d983e38b Mon Sep 17 00:00:00 2001 From: mangoplane Date: Sat, 21 Sep 2024 20:04:12 +1000 Subject: [PATCH 1/5] fix: resolve loop variable 'i' captured by func literal in closure --- config/config_test.go | 1 + 1 file changed, 1 insertion(+) diff --git a/config/config_test.go b/config/config_test.go index 936622b06c..eac0df51d2 100644 --- a/config/config_test.go +++ b/config/config_test.go @@ -773,6 +773,7 @@ func TestLocal_ValidateP2PHybridConfig(t *testing.T) { for i, test := range tests { test := test + i := i t.Run(fmt.Sprintf("test=%d", i), func(t *testing.T) { t.Parallel() From 7b6b6c2c4c6302b6f13fd10e8150afe7e728f924 Mon Sep 17 00:00:00 2001 From: mangoplane Date: Sun, 22 Sep 2024 15:30:48 +1000 Subject: [PATCH 2/5] AVM: Adding bmodexp --- data/transactions/logic/assembler_test.go | 12 ++++- data/transactions/logic/doc.go | 5 +- data/transactions/logic/eval.go | 20 ++++++++ data/transactions/logic/eval_test.go | 50 ++++++++++++++++++++ data/transactions/logic/opcodes.go | 1 + data/transactions/logic/teal.tmLanguage.json | 2 +- 6 files changed, 85 insertions(+), 5 deletions(-) diff --git a/data/transactions/logic/assembler_test.go b/data/transactions/logic/assembler_test.go index 10d86f476a..6e0dce6484 100644 --- a/data/transactions/logic/assembler_test.go +++ b/data/transactions/logic/assembler_test.go @@ -439,6 +439,13 @@ dup; dup falcon_verify ` +const bmodexpNonsense = ` +pushbytes 0x0123456789abcd +pushbytes 0x0123456789abcd +pushbytes 0x0123456789abcd +bmodexp +` + const v8Nonsense = v7Nonsense + switchNonsense + frameNonsense + matchNonsense + boxNonsense const v9Nonsense = v8Nonsense @@ -450,7 +457,7 @@ const spliceNonsence = ` const v10Nonsense = v9Nonsense + pairingNonsense + spliceNonsence -const v11Nonsense = v10Nonsense + incentiveNonsense + stateProofNonsense +const v11Nonsense = v10Nonsense + incentiveNonsense + stateProofNonsense + bmodexpNonsense const v6Compiled = "2004010002b7a60c26050242420c68656c6c6f20776f726c6421070123456789abcd208dae2087fbba51304eb02b91f656948397a7946390e8cb70fc9ea4d95f92251d047465737400320032013202320380021234292929292b0431003101310231043105310731083109310a310b310c310d310e310f3111311231133114311533000033000133000233000433000533000733000833000933000a33000b33000c33000d33000e33000f3300113300123300133300143300152d2e01022581f8acd19181cf959a1281f8acd19181cf951a81f8acd19181cf1581f8acd191810f082209240a220b230c240d250e230f2310231123122313231418191a1b1c28171615400003290349483403350222231d4a484848482b50512a632223524100034200004322602261222704634848222862482864286548482228246628226723286828692322700048482371004848361c0037001a0031183119311b311d311e311f312023221e312131223123312431253126312731283129312a312b312c312d312e312f447825225314225427042455220824564c4d4b0222382124391c0081e80780046a6f686e2281d00f23241f880003420001892224902291922494249593a0a1a2a3a4a5a6a7a8a9aaabacadae24af3a00003b003c003d816472064e014f012a57000823810858235b235a2359b03139330039b1b200b322c01a23c1001a2323c21a23c3233e233f8120af06002a494905002a49490700b400b53a03b6b7043cb8033a0c2349c42a9631007300810881088120978101c53a8101c6003a" @@ -475,8 +482,9 @@ const v10Compiled = v9Compiled + pairingCompiled + spliceCompiled const incentiveCompiled = "757401" const stateProofCompiled = "80070123456789abcd86494985" +const bmodexpCompiled = "80070123456789abcd80070123456789abcd80070123456789abcde6" -const V11Compiled = v10Compiled + incentiveCompiled + stateProofCompiled +const V11Compiled = v10Compiled + incentiveCompiled + stateProofCompiled + bmodexpCompiled var nonsense = map[uint64]string{ 1: v1Nonsense, diff --git a/data/transactions/logic/doc.go b/data/transactions/logic/doc.go index 3bab156561..3dfb2f0d7b 100644 --- a/data/transactions/logic/doc.go +++ b/data/transactions/logic/doc.go @@ -273,7 +273,8 @@ var opDescByName = map[string]OpDesc{ "b^": {"A bitwise-xor B. A and B are zero-left extended to the greater of their lengths", "", nil}, "b~": {"A with all bits inverted", "", nil}, - "bsqrt": {"The largest integer I such that I^2 <= A. A and I are interpreted as big-endian unsigned integers", "", nil}, + "bsqrt": {"The largest integer I such that I^2 <= A. A and I are interpreted as big-endian unsigned integers", "", nil}, + "bmodexp": {"A raised to the Bth power modulo C. A, B and C are interpreted as big-endian unsigned integers limited to 4096 bytes. Fail if C is zero.", "", nil}, "log": {"write A to log state of the current application", "`log` fails if called more than MaxLogCalls times in a program, or if the sum of logged bytes exceeds 1024 bytes.", nil}, "itxn_begin": {"begin preparation of a new inner transaction in a new transaction group", "`itxn_begin` initializes Sender to the application address; Fee to the minimum allowable, taking into account MinTxnFee and credit from overpaying in earlier transactions; FirstValid/LastValid to the values in the invoking transaction, and all other fields to zero or empty values.", nil}, @@ -352,7 +353,7 @@ func OpDocExtra(opName string) string { var OpGroups = map[string][]string{ "Arithmetic": {"+", "-", "/", "*", "<", ">", "<=", ">=", "&&", "||", "shl", "shr", "sqrt", "bitlen", "exp", "==", "!=", "!", "itob", "btoi", "%", "|", "&", "^", "~", "mulw", "addw", "divw", "divmodw", "expw"}, "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 Arithmetic": {"b+", "b-", "b/", "b*", "b<", "b>", "b<=", "b>=", "b==", "b!=", "b%", "bsqrt", "bmodexp"}, "Byte Array Logic": {"b|", "b&", "b^", "b~"}, "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"}, diff --git a/data/transactions/logic/eval.go b/data/transactions/logic/eval.go index 4da436a1b6..9ee5a50a2f 100644 --- a/data/transactions/logic/eval.go +++ b/data/transactions/logic/eval.go @@ -2325,6 +2325,26 @@ func opBytesNeq(cx *EvalContext) error { return opNot(cx) } +func opBytesModExp(cx *EvalContext) error { + result := new(big.Int) + last := len(cx.Stack) - 1 // z + prev := last - 1 // y + pprev := last - 2 // x + + z := new(big.Int).SetBytes(cx.Stack[last].Bytes) + y := new(big.Int).SetBytes(cx.Stack[prev].Bytes) + x := new(big.Int).SetBytes(cx.Stack[pprev].Bytes) + if z.BitLen() == 0 { + return errors.New("modulo by zero") + } + + result.Exp(x, y, z) + + cx.Stack[pprev].Bytes = result.Bytes() + cx.Stack = cx.Stack[:prev] + return nil +} + func opBytesModulo(cx *EvalContext) error { result := new(big.Int) var inner error diff --git a/data/transactions/logic/eval_test.go b/data/transactions/logic/eval_test.go index c8f7a8bc5f..e0e41a37e4 100644 --- a/data/transactions/logic/eval_test.go +++ b/data/transactions/logic/eval_test.go @@ -5065,6 +5065,56 @@ func TestBitLen(t *testing.T) { } +func TestBytesModExp(t *testing.T) { + partitiontest.PartitionTest(t) + t.Parallel() + type TestOutcome int + const ( + Accept TestOutcome = iota + Reject + Panic + ) + type ModexpTestVector struct { + Base string + Exponent string + Modulus string + Result string + TestOutcome TestOutcome + } + modexpTestVectors := []ModexpTestVector{ + {"0x01", "0x01", "0x", "0x00", Panic}, // Modulo of 0 should panic + {"0x01", "0x01", "0x0000", "0x00", Panic}, // Modulo of 0 should panic + {"0x00", "0x00", "0x01", "0x", Accept}, + {"0xfecd94e51b7227573693217cffee2069b16e86509aaeb141e3918b9522b48dfdb8cf6f842a5b25602d3a509addb561ddbee848b4a0d68473f142e0b895c99a7e5c1dd2a9d3aac4e65e87b61a7cb4689afeaf1a28fa642bd35a56e6fc123b60c1fd34c33fce472dc5a6bbcaa136a89af1df0b4c85aa99cf34f11b0d605709778f876295eee07828000ff37fa045b279fa12e0b0e99e525705acca77b54d4210fdcde48374152e97753fb9aae79d48e82abfb9e9afc102e78fe3d3b21218982ca78d044291b8d8ae715ead3b7690de00f67a91ec0eb85d4c0c2736215f14678a8ea239f8425151f7e31bb39000a6", "0xd27369499b4e38c037632ee1f1a963f1f4d9275f8a514a335ed46f64061dd354e7438f233a77ba2d1d372158c17078409e72699e909452a663497145d7f4d65932e8a49a9add52783531e5352d17085028ed0a7551439e4e4bf7c287ba0b9176532f300c2710d86d3380f64fced370fd61c8f3b52c4136aff1b8f7190ea220ee50d25182b37990e09f765c2aa65e4bb8930fc7d1e3d8466d988610a5ad1b7067851b95d7c88d5a57a2e710860193580c015fe067627dcbe157887c29b9709ed8e04dee40521fbf6f7472ef0e38cef45ea6b1b0dc3f9d8a0ca11376ac9f92512596d82ce1000e4ad0551f807060afc2", "0x27a889b93153f4a045dc7583c169fe4a86fa1909ccc1a4183fe577be60905c76e3b2990b525ab40afc36dd9009b6e5b89c7789f09f72ee36bf011501b797a7520f0f35b636f5f1457908e12746a13243b27e02814570d46ceb35bdb8bf5dbd45b1854f859ef5d1c6fc7c21450ead9002fb99e05879d7531463fb565bbe9fc0c336d11e686f2d7cd9f96423243bad8907a955966df2", "0x1159c95dfd2d6010f7df10078b3bca2681d8bc892596462d1bed9beb64b2d349c6b2422d12cd5c759c517e9d6861b3cd41a301b671c09c06fc8c463f958a82695f451b5b348361e8016105453d79b63cd6df2d0ab9dc37228dc71effeb7036b7daa971f94507b53d673df31ccad70295f26a91b648c962db1c278f97f7c6848c9b6eb14a66c350d86a541aafae7f22b1d64876369e", Accept}, + {"0xb83ede301f43216b751761b94103ca4c01352ddc0eec69abf69ecf70fdd9f7aacf9dda9518eba3862d138bd2e7336b0a8621e83b22e25b5347507336b061e38d48c083722b523c33509c1b9a0d30a3da8ca7f5b2fb8d0095ca48a7d4c5c9a34f222b43eaa3c66cd18c37b0ea4016356ebfb3a888db8a3c90d03ebab84d1b43a57d34cf781a78df7ae3f87102a12bb6412a42a642d649f1a349235b080322e585745c6ebaffd49919f1bed598414e8ea6edb191e17868e4d2353337509fd29c7053f67e27b261e478f37b5d59e4f667f4d51bb354ffd9a90e94bd8ec947564033ee1d578b1fe8d7", "0x183e792802e3e670be1d570a5658672500c287625582b7743de11e8e80361613a86419e464fdf57e0c504c155e6b7febdf1a5833f39b7fa5891386f8dfaa985dad5b1bf0001ada176bf05b5129c3d16fcad6be460feaed369cbc986929f94be839a82b5341c7a791f014f5ed0fdf0f3c6a1becbe23c4e0aa4ca9495a087a37464ff46745b6e7139c0e1fc5d2ec53d48495714bb1ccbadc0dca5275fc33424f0c9c057cd41b4d094c87fba00015ec5ed12ee115c3704898c4e702bd64de7879eeccee135957125dcf1c43b5a4ce424b", "0x379f241e6a9c0aed86705cf6ecbc9bfb6533cd757ed53facc7ec1f95c9139068560a3e185ae01401e0e05251eb2b036986cb17be92d8f46622800a64ae8d0b8d2d2b649a4d6be28e2a6fb705f349bd7513a055a33c92e140ad9643e7710459be1f1b4930f46a447bc0ec0552602d76f3616b2030613976afa00b961e7fa909ce2bf77a040a7ba72277c5406883ef2946e7571e192c3c0bfe5e9f66a786a9", "0x0fe90441ccf81a0a8227155936d90dada4", Reject}, + {"0x43f4df0787ae52b4433b7a5fe0a55993cb1cf79b0e9318f85a90b7ba7c0ced2603d464113b82ea7986ac5249e2266db648ebb23529c0a1d732ffdacdcba22fc88e184d", "0x0402678ddba1793fa049e81f30b2a825d97db413573f13d9ec9dd54523e5ee202308b9c0c20b26d4949c626ad62d3768e38316b1c7fc0a1ca3f84697f350408d10318bf39d8dffad2254cd5519de8a0defb8e17aad2a5f05cb5ac0f25c0f5274653406216212ad38c733959adbfb31ca531dddc9f8e5ce0478fe30b12d422732b401c103e96140cba3ec026511f0b3d2355d079910834f0cec1847bb9d9a2d040f095b2761e4bd26e79600ae7c575b80c54893131eb26302c4107e7f83acc5754840d8588e4803fe3bcdbd3c7a26a109a22407de5809cdbd525f8fd41fac561e301f08928638", "0xdd9224855029854c02a3c1b92a62a41e8d32ef64dbfd39858413df75631ce8b442d845fe256f6bc6b842f192fa27ba627a45bbcee0b9a606f761d3d753566cf8ed2a6cc3edffb011d190a2b7f31c15923e58da6b7aaaa775fa948cac4723c164bb3c084354bcd90b1dc19d338a4074a68d4ee1e81eca0fa2b1eeaee0254aa307a3adeabe06550996b59a4d3572021e3a5cb670d113030b155eed5be224d0800296d0b4181066dbdb36ceabb178b29527b2ecd5fc8443801e2e13422a4c9004013be315c6fbfe48e3d1ac858886426381aef76d8e0fd3a2ca9b1147f2da2cfef3988cec0d227666fe8b5919a67ed8", "0x0e2611da26bfb2a255a28659b32c4ad4031c9a519f0008280c315ebe0981428c717f70e293956abf2313286742bfa569e70ba883e337c33d0ba54f1eed68499f9be4e174451c22d940e4e50dd0c26578b1da11a3f174ba77f85988839c80c916de370274e30864de05ddb805713d2cad6d7c908db8ceec7e7e280eb65dd9e6f74bd031b1d6db72475697af7c8851a22b003c23b6139818576e11c8dbe667792e54cba5acce53b18747a09d43696042d3024bf04d23c3b2264527bd26d4163402389687dcbdacb1b75dfb1ed156b2faf5bb4f3284298b558ed4dd5ba754df0b7a5c3bdbf8f4619487ace3992e5921", Accept}, + {"0x43e3f4a2a30309f52331c8b23e9f2c2c5bfb5c3bef8b69a4b58ddd185b8b63b1f23b21ee7a0e85893433facfc135c7e21f39e06a4ad71bc26268acb480907a883685963bbc4c4ec52ab52c6ae681cd61245c3d8bd8f5bba2b5e4e123357dba12235c61ce1549f5c60f400afa453f5db65bf72b1d5d20b254b0c306a86a9e68ac2f0e226e", "0x4504b93f905be9f35e38e507d0fd5f666ecd212fde7579f23a47cc9910b54f9b420c2fcd54e8fbec2bb24ccd050fdc0300d3", "0x381ddee4f5f83bc09da93ede2d13022628f443f4aef73ef740ea50e6aaf377f67c3c21c1d858c46978076a5926e9d803999f911f2af2bcaa82ae02f0b3c48f4467ed545763d18c9b157376cc7a6aac2b0669abbc6894b5784f01bb786545933ad8bfd975a041ff03cc81b60677b7afc0aa059c4c47a41af3f30e33fe08743686cbc15049e26e13cfbf719515229281c59ee99b7a9a6aaa110df9a2d16b58394f704d4982ceed8e441a62d809c0a842f16bc85e8a9bb6ff3bf027cc0e73cca9ff285bc74e08d857629f9b5c0d051dcf88221ac9687245e7ee7e6d877072fde59222ff", "0x9312bfc6064fcbe01c7bf1ac1bba80a2b0607faaac2f0f102270129abf5a56dc50b3145c79aa5babda0dc85d7205f742da145d65764147fe9ca027d0e15affc9963ec7abaac1a025654213d91a22a11055f00621dd3c1aa5b7180e70de3a68ac7d3dde0088adf0006fe80950ee8d3c3e8bad87d68f6d9e45af1729ea2ffcd81b117f48be33e1fa1254a1e49bf67cf6def9df3d7030f88ae0d0cda5c999bcdb2c2f631508abc5a6ce3080c27a274d5b7d7d", Reject}, + {"0x2e6bebf6e587185ce2b74db841a5f7d681aedd53b7d0fa76a1e9dbeb3dcd60f021affa201c192257d89642dbf6afffd1a272c0f7b4e30b88", "0x4396069f7dd294400e725602c6c8ad4f3fe0301578c62537138c3bf98211c096a86a1448b2e57b0a005dec2eb631d8eb2aa9974ba3c3343a5170cac4094296937606fd318439f7f40dcb2c6b5a4f6059829e87b39eae61a40cc27ae22466f2c7b5cf78d7a2299aed6df7c5e69c80f450f979bfae39a5ed82343a02cc61e877079ee26b42b9afc01d1f60627b4bfbfe12a5", "0x676326af0980eeee7f6deeb6b77609df8bc847aa6e20c1f15bb070d8650c9427a4862b1e08fbed2f88ff18e1085c152ef80534b9dfd56a7c488c7068103e76ae730715997214d3c528515d572296941cf89250010b3bef7fbf175e55faeaf36f5746814ef94da60bdedfc8b8fd02434cd5122f56c5c36567a6a627e7cda8a36e90756e29cf8091465d140e5037bce8abc4f59b9160f580affb0845095071764754449fb485dd5ba1af", "0x2356ca087f69fe3fd129686b9406f448eb71bf04576cfb19e01731f541fb487409a7ac705b32de77511dc7952aa26980661cfc77d08a69e74eedeea60befe46af667b8c95b946c7535b3ac0c6210944a1f3804a7cf16c033adad01e6cddf29eee99db6245f3408db3dc77d32d83666535c60bbdcf79a251c5690fbb93830ec942607182fe0dd45739b9587fad72c98a8462f1fde205253b08b857d91a947192310df13a592f1417b78", Accept}, + {"0xefe0ed52aa48ac1954d289cddc48fe2fa9d2fd0a30ec80558d120df81dfd1bd5bdafc6db6c1be75408c8913667966a67eeae3d4660c51365cd126acbcff0896a242f998d6cdd12effe1519826eb869762835d33e30ecfa9fa1c3c26b8481d106e301cb9d7d53d5499fe7b38107e222de26cb2a5dd2cdba60dca3f8cfc35e512b5f4ba6429be53041a8fbcea34546b3562f20668d414d8025448b46fdcf2b6665ac6eab707642b5", "0x815178f225ffa7735b81058aeb7618db87d8e027b56d76dba76acfca305df3bf1039e86a2485d525894528", "0xe8cb702599322c16a07935ebaa175e1da2c090807209942f43df5c6db4732f08235da740218ce9ab2b654e53d8f102a0a4b0aca861270ca6788aebcd223d2ac3640ccdaa43aac14970751a6eafed7180a51a4d6de93b3e5e7e74f8a55bef5caf5a096e11354cae423d770fe1bc6682752b639e7510d7a2b77d44bf104c3333ce029d4f7e49255fd50e6ee2ba1002fc7c2c17b9f17053dc11135bc5b5e5f6e7cc075b3d0e658affc64b24819a3a8458a4467faa76112ffb6c061a96a199f2ef4f4e9a2b91687c7be85f009029c60495", "0x5437f7393e93182cc931add5c2ab61373c0a83a9c9713b91c0d880325cb6153a369feb6c2755c68f18444e1e67f0b16bcfba717c3b61833ae1c4a28b64b6860aaaf9fdebede0ee2e6aa88b18ac1e39ab5307678669de5d1046e800585adca7c560f923eb3511afccb3eb52c507a9e96a266aac75439b289a0756415f50658d07ff5ef236f3ffc6e5a57f4b5e27785737fbb77f4e0c780de0dbdafe2de14ec61344346ecd6f2db6cf6f0b12c95d7103f68fb837d022504a04f69a", Reject}, + {"0x5aaf78fa0137ed7a80a760cb1f00fe76f8dba1048bf35db85ed43d7081fff9c7fd61e71fe7a42ef861c081786d0b92053263a92d0491403f31bcddac325b7012d1078c19c17a16a22b57eed143f6d1aa3c7cb823479f8314a87db3142aaf50a8ec1eb8afec5c09bc5c1f97b5f617681ff9cafaf6b5bd6f186892e2016f58", "0xda431fbf1062b9ef1be8812d7d6870257f11aba4b9f27ce4f3db13200111a2e6862219042331d8e31c2438f9f6bc0dd77708200480d5c26632b9bac060daf4a4f74fd966fab0fcaea1853b3478eb6c3088b732a5ac20c0c13d5a3ae65fe23b", "0x57fb8a5ff255e23da812337e4145d4eaa11529de3894741886ae99a839bed9a10ae06719a0a820a34295a62e2534eaf0431b6be1b5187384dff144e828932622af0624976cb4b9660833385346cbc2d55379d0c72eda68a10202be3e8c92cc8d151864d2d465abc9ec6759f4f2e341cd4dcf4a4fac1ce4a480e065eaf859dff8799646bf9638535979cc8b616215b9c737d59bc0146520d415511aaef942a923afa58435d9d5", "0x05a08475905993424f0ce051bba9213855c74d601ed82089ec8f804b5e29275ec2b6b53ea813c1931a248418500a1a73e6c94a7a9f72df4cfd863218a928c999e8bb65106c606bc40e068b732e312b63b6ce5f6370402f9f576fe33d981ed9f06bcbc653aea90e3a2e7359560001e787119f8ee1d90695753582e52e077bd848c8c6eec421a2b79531fc15798c044ead4a81bc40b98964c9b21ff49c0a5da2d20752ca63a0d8", Accept}, + {"0x7afd6101ca03eee6db2ee5bd17c4df4645d3099c5b69d01efddd9656f14a5085534f1bbab0e9213e827715c5bd4abf8f9a7a1052cf1afb2b6332ec74c4b18e6a6ef976bfb70c2d", "0x33fe913d149938164862fe788a7dfaa901690376e3e193523fc92afc6e8e1ef4fb40ed01273231942a2b5b4d7d59b5e65b3397fa61c7453b1559b177b1b160fff8cf48867097e887c4be19a6c33ba156cae132090b4f8b7e54a501431a04f066b003ca2868e4cef065a1d1f5903ee581ac3c97003d71160fe3e643a42126c08e17c6b1675c8407bc6f3ad4ccb858535cbe132c8b48e9fbedcf2e222cec319a95a3c4f75df10463b11bd97e810c623c92ab8efe5d31f0d89ad85ac8", "0x757c4d7f4d108027363a6181eb0d950bc515afe7d7dd103cfadce2295030430840a45b4e541c4966e9f991ee219b26ace999b7a0d07d9e10414644daf591b09a04696705cc2555ec7c05dfc9e51d349ae25a96106f99a620d4962edae0b940c62276c6", "0x65fbf3319e294a7109a1f607c3379360f78df96c940b7a244c725a23cc632f4dd4c6283bddbe8dfb46c69de79dc337aea892708c5de1a27c6a422f41fce6ab5b19100de32081c2a066e51cacfbf5d8c76bed6a502ada2ff044619e3f5d196d401ba3a45cc8ebc8767750239ecf326b3eb658ef970baeefa40fd1e1dbcbdd7d6a7838d6a20595765021d5e3f8fe6a96c4a346f8a26990317de9c57a6a309a132a6b6dfad21c1d7f707e8607e497b7cca31b9d5bf804af4d46", Reject}, + } + + for _, modexpTestVector := range modexpTestVectors { + progText := fmt.Sprintf(`byte %s +byte %s +byte %s +bmodexp + +byte %s +==`, modexpTestVector.Base, modexpTestVector.Exponent, modexpTestVector.Modulus, modexpTestVector.Result) + switch modexpTestVector.TestOutcome { + case Accept: + testAccepts(t, progText, 11) + case Reject: + testRejects(t, progText, 11) + case Panic: + testPanics(t, progText, 11) + } + } + +} + func TestBytesMath(t *testing.T) { partitiontest.PartitionTest(t) diff --git a/data/transactions/logic/opcodes.go b/data/transactions/logic/opcodes.go index f3f8bfe37d..5f9639e048 100644 --- a/data/transactions/logic/opcodes.go +++ b/data/transactions/logic/opcodes.go @@ -798,6 +798,7 @@ var OpSpecs = []OpSpec{ costByField("g", &EcGroups, []int{ BN254g1: 630, BN254g2: 3_300, BLS12_381g1: 1_950, BLS12_381g2: 8_150})}, + {0xe6, "bmodexp", opBytesModExp, proto("bbb:b"), 11, costly(2000)}, // TODO: refine cost model for bmodexp } // OpcodesByVersion returns list of opcodes available in a specific version of TEAL diff --git a/data/transactions/logic/teal.tmLanguage.json b/data/transactions/logic/teal.tmLanguage.json index 53984e8dd2..118a250a76 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|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" + "match": "^(\\!|\\!\\=|%|\u0026|\u0026\u0026|\\*|\\+|\\-|/|\\\u003c|\\\u003c\\=|\\=\\=|\\\u003e|\\\u003e\\=|\\^|addw|bitlen|btoi|divmodw|divw|exp|expw|itob|mulw|shl|shr|sqrt|\\||\\|\\||\\~|b\\!\\=|b%|bmodexp|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" } ] }, From a72572d45bebd8dd7684293c4bb9d80a5112efb7 Mon Sep 17 00:00:00 2001 From: mangoplane Date: Tue, 15 Oct 2024 10:13:53 +1100 Subject: [PATCH 3/5] feat: add BenchmarkBytesModExp to benchmark bmodexp --- data/transactions/logic/eval_test.go | 52 ++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/data/transactions/logic/eval_test.go b/data/transactions/logic/eval_test.go index e0e41a37e4..b9e0f273a8 100644 --- a/data/transactions/logic/eval_test.go +++ b/data/transactions/logic/eval_test.go @@ -17,6 +17,7 @@ package logic import ( + "crypto/rand" "encoding/base64" "encoding/binary" "encoding/hex" @@ -5065,6 +5066,57 @@ func TestBitLen(t *testing.T) { } +func BenchmarkBytesModExp(b *testing.B) { + type ModexpTestVector struct { + Base string + Exponent string + Modulus string + Name string + } + + // Function to generate a random hex string of a specified length in bytes + generateRandomHexString := func(length int) string { + bytes := make([]byte, length) + rand.Read(bytes) + return fmt.Sprintf("0x%x", bytes) + } + + // Define the accepted test vectors using nested loops + modexpTestVectors := []ModexpTestVector{} + incr := 128 + maxDim := 1024 + for baseLen := incr; baseLen <= maxDim; baseLen += incr { + for expLen := incr; expLen <= maxDim; expLen += incr { + for modLen := incr; modLen <= maxDim; modLen += incr { + modexpTestVectors = append(modexpTestVectors, ModexpTestVector{ + Name: fmt.Sprintf(`TestVector_Dim(%d,%d,%d)`, baseLen, expLen, modLen), + Base: generateRandomHexString(baseLen), + Exponent: generateRandomHexString(expLen), + Modulus: generateRandomHexString(modLen), + }) + } + } + } + b.Run("bmod_cost", func(b *testing.B) { + b.ReportAllocs() + progText := fmt.Sprintf(`byte %s; byte %s;`, generateRandomHexString(64), generateRandomHexString(64)) + " b%; pop" + benchmarkOperation(b, "", progText, "int 1") + }) + b.Run("max_bmodexp_cost", func(b *testing.B) { + b.ReportAllocs() + progText := fmt.Sprintf(`byte %s; byte %s; byte %s; bmodexp; pop`, generateRandomHexString(4096), generateRandomHexString(4096), generateRandomHexString(4096)) + benchmarkOperation(b, "", progText, "int 1") + }) + // Iterate through the test vectors and benchmark the bmodexp computation + for _, tv := range modexpTestVectors { + b.Run(tv.Name, func(b *testing.B) { + b.ReportAllocs() + progText := fmt.Sprintf(`byte %s; byte %s; byte %s; bmodexp; pop`, tv.Base, tv.Exponent, tv.Modulus) + benchmarkOperation(b, "", progText, "int 1") + }) + } +} + func TestBytesModExp(t *testing.T) { partitiontest.PartitionTest(t) t.Parallel() From f33a9373016d6d670dd16d064fb6950fd4c8e8cd Mon Sep 17 00:00:00 2001 From: mangoplane <104189015+mangoplane@users.noreply.github.com> Date: Tue, 15 Oct 2024 10:40:03 +1100 Subject: [PATCH 4/5] feat: extended linearCost to allow for arbitrary opcode cost functions, accounting for cost computation and doc generation --- data/transactions/logic/eval_test.go | 35 ++++++++++------ data/transactions/logic/opcodes.go | 62 ++++++++++++++++++++++++---- 2 files changed, 77 insertions(+), 20 deletions(-) diff --git a/data/transactions/logic/eval_test.go b/data/transactions/logic/eval_test.go index b9e0f273a8..0ff17ddfd8 100644 --- a/data/transactions/logic/eval_test.go +++ b/data/transactions/logic/eval_test.go @@ -5131,20 +5131,26 @@ func TestBytesModExp(t *testing.T) { Exponent string Modulus string Result string + LogicCost int TestOutcome TestOutcome } modexpTestVectors := []ModexpTestVector{ - {"0x01", "0x01", "0x", "0x00", Panic}, // Modulo of 0 should panic - {"0x01", "0x01", "0x0000", "0x00", Panic}, // Modulo of 0 should panic - {"0x00", "0x00", "0x01", "0x", Accept}, - {"0xfecd94e51b7227573693217cffee2069b16e86509aaeb141e3918b9522b48dfdb8cf6f842a5b25602d3a509addb561ddbee848b4a0d68473f142e0b895c99a7e5c1dd2a9d3aac4e65e87b61a7cb4689afeaf1a28fa642bd35a56e6fc123b60c1fd34c33fce472dc5a6bbcaa136a89af1df0b4c85aa99cf34f11b0d605709778f876295eee07828000ff37fa045b279fa12e0b0e99e525705acca77b54d4210fdcde48374152e97753fb9aae79d48e82abfb9e9afc102e78fe3d3b21218982ca78d044291b8d8ae715ead3b7690de00f67a91ec0eb85d4c0c2736215f14678a8ea239f8425151f7e31bb39000a6", "0xd27369499b4e38c037632ee1f1a963f1f4d9275f8a514a335ed46f64061dd354e7438f233a77ba2d1d372158c17078409e72699e909452a663497145d7f4d65932e8a49a9add52783531e5352d17085028ed0a7551439e4e4bf7c287ba0b9176532f300c2710d86d3380f64fced370fd61c8f3b52c4136aff1b8f7190ea220ee50d25182b37990e09f765c2aa65e4bb8930fc7d1e3d8466d988610a5ad1b7067851b95d7c88d5a57a2e710860193580c015fe067627dcbe157887c29b9709ed8e04dee40521fbf6f7472ef0e38cef45ea6b1b0dc3f9d8a0ca11376ac9f92512596d82ce1000e4ad0551f807060afc2", "0x27a889b93153f4a045dc7583c169fe4a86fa1909ccc1a4183fe577be60905c76e3b2990b525ab40afc36dd9009b6e5b89c7789f09f72ee36bf011501b797a7520f0f35b636f5f1457908e12746a13243b27e02814570d46ceb35bdb8bf5dbd45b1854f859ef5d1c6fc7c21450ead9002fb99e05879d7531463fb565bbe9fc0c336d11e686f2d7cd9f96423243bad8907a955966df2", "0x1159c95dfd2d6010f7df10078b3bca2681d8bc892596462d1bed9beb64b2d349c6b2422d12cd5c759c517e9d6861b3cd41a301b671c09c06fc8c463f958a82695f451b5b348361e8016105453d79b63cd6df2d0ab9dc37228dc71effeb7036b7daa971f94507b53d673df31ccad70295f26a91b648c962db1c278f97f7c6848c9b6eb14a66c350d86a541aafae7f22b1d64876369e", Accept}, - {"0xb83ede301f43216b751761b94103ca4c01352ddc0eec69abf69ecf70fdd9f7aacf9dda9518eba3862d138bd2e7336b0a8621e83b22e25b5347507336b061e38d48c083722b523c33509c1b9a0d30a3da8ca7f5b2fb8d0095ca48a7d4c5c9a34f222b43eaa3c66cd18c37b0ea4016356ebfb3a888db8a3c90d03ebab84d1b43a57d34cf781a78df7ae3f87102a12bb6412a42a642d649f1a349235b080322e585745c6ebaffd49919f1bed598414e8ea6edb191e17868e4d2353337509fd29c7053f67e27b261e478f37b5d59e4f667f4d51bb354ffd9a90e94bd8ec947564033ee1d578b1fe8d7", "0x183e792802e3e670be1d570a5658672500c287625582b7743de11e8e80361613a86419e464fdf57e0c504c155e6b7febdf1a5833f39b7fa5891386f8dfaa985dad5b1bf0001ada176bf05b5129c3d16fcad6be460feaed369cbc986929f94be839a82b5341c7a791f014f5ed0fdf0f3c6a1becbe23c4e0aa4ca9495a087a37464ff46745b6e7139c0e1fc5d2ec53d48495714bb1ccbadc0dca5275fc33424f0c9c057cd41b4d094c87fba00015ec5ed12ee115c3704898c4e702bd64de7879eeccee135957125dcf1c43b5a4ce424b", "0x379f241e6a9c0aed86705cf6ecbc9bfb6533cd757ed53facc7ec1f95c9139068560a3e185ae01401e0e05251eb2b036986cb17be92d8f46622800a64ae8d0b8d2d2b649a4d6be28e2a6fb705f349bd7513a055a33c92e140ad9643e7710459be1f1b4930f46a447bc0ec0552602d76f3616b2030613976afa00b961e7fa909ce2bf77a040a7ba72277c5406883ef2946e7571e192c3c0bfe5e9f66a786a9", "0x0fe90441ccf81a0a8227155936d90dada4", Reject}, - {"0x43f4df0787ae52b4433b7a5fe0a55993cb1cf79b0e9318f85a90b7ba7c0ced2603d464113b82ea7986ac5249e2266db648ebb23529c0a1d732ffdacdcba22fc88e184d", "0x0402678ddba1793fa049e81f30b2a825d97db413573f13d9ec9dd54523e5ee202308b9c0c20b26d4949c626ad62d3768e38316b1c7fc0a1ca3f84697f350408d10318bf39d8dffad2254cd5519de8a0defb8e17aad2a5f05cb5ac0f25c0f5274653406216212ad38c733959adbfb31ca531dddc9f8e5ce0478fe30b12d422732b401c103e96140cba3ec026511f0b3d2355d079910834f0cec1847bb9d9a2d040f095b2761e4bd26e79600ae7c575b80c54893131eb26302c4107e7f83acc5754840d8588e4803fe3bcdbd3c7a26a109a22407de5809cdbd525f8fd41fac561e301f08928638", "0xdd9224855029854c02a3c1b92a62a41e8d32ef64dbfd39858413df75631ce8b442d845fe256f6bc6b842f192fa27ba627a45bbcee0b9a606f761d3d753566cf8ed2a6cc3edffb011d190a2b7f31c15923e58da6b7aaaa775fa948cac4723c164bb3c084354bcd90b1dc19d338a4074a68d4ee1e81eca0fa2b1eeaee0254aa307a3adeabe06550996b59a4d3572021e3a5cb670d113030b155eed5be224d0800296d0b4181066dbdb36ceabb178b29527b2ecd5fc8443801e2e13422a4c9004013be315c6fbfe48e3d1ac858886426381aef76d8e0fd3a2ca9b1147f2da2cfef3988cec0d227666fe8b5919a67ed8", "0x0e2611da26bfb2a255a28659b32c4ad4031c9a519f0008280c315ebe0981428c717f70e293956abf2313286742bfa569e70ba883e337c33d0ba54f1eed68499f9be4e174451c22d940e4e50dd0c26578b1da11a3f174ba77f85988839c80c916de370274e30864de05ddb805713d2cad6d7c908db8ceec7e7e280eb65dd9e6f74bd031b1d6db72475697af7c8851a22b003c23b6139818576e11c8dbe667792e54cba5acce53b18747a09d43696042d3024bf04d23c3b2264527bd26d4163402389687dcbdacb1b75dfb1ed156b2faf5bb4f3284298b558ed4dd5ba754df0b7a5c3bdbf8f4619487ace3992e5921", Accept}, - {"0x43e3f4a2a30309f52331c8b23e9f2c2c5bfb5c3bef8b69a4b58ddd185b8b63b1f23b21ee7a0e85893433facfc135c7e21f39e06a4ad71bc26268acb480907a883685963bbc4c4ec52ab52c6ae681cd61245c3d8bd8f5bba2b5e4e123357dba12235c61ce1549f5c60f400afa453f5db65bf72b1d5d20b254b0c306a86a9e68ac2f0e226e", "0x4504b93f905be9f35e38e507d0fd5f666ecd212fde7579f23a47cc9910b54f9b420c2fcd54e8fbec2bb24ccd050fdc0300d3", "0x381ddee4f5f83bc09da93ede2d13022628f443f4aef73ef740ea50e6aaf377f67c3c21c1d858c46978076a5926e9d803999f911f2af2bcaa82ae02f0b3c48f4467ed545763d18c9b157376cc7a6aac2b0669abbc6894b5784f01bb786545933ad8bfd975a041ff03cc81b60677b7afc0aa059c4c47a41af3f30e33fe08743686cbc15049e26e13cfbf719515229281c59ee99b7a9a6aaa110df9a2d16b58394f704d4982ceed8e441a62d809c0a842f16bc85e8a9bb6ff3bf027cc0e73cca9ff285bc74e08d857629f9b5c0d051dcf88221ac9687245e7ee7e6d877072fde59222ff", "0x9312bfc6064fcbe01c7bf1ac1bba80a2b0607faaac2f0f102270129abf5a56dc50b3145c79aa5babda0dc85d7205f742da145d65764147fe9ca027d0e15affc9963ec7abaac1a025654213d91a22a11055f00621dd3c1aa5b7180e70de3a68ac7d3dde0088adf0006fe80950ee8d3c3e8bad87d68f6d9e45af1729ea2ffcd81b117f48be33e1fa1254a1e49bf67cf6def9df3d7030f88ae0d0cda5c999bcdb2c2f631508abc5a6ce3080c27a274d5b7d7d", Reject}, - {"0x2e6bebf6e587185ce2b74db841a5f7d681aedd53b7d0fa76a1e9dbeb3dcd60f021affa201c192257d89642dbf6afffd1a272c0f7b4e30b88", "0x4396069f7dd294400e725602c6c8ad4f3fe0301578c62537138c3bf98211c096a86a1448b2e57b0a005dec2eb631d8eb2aa9974ba3c3343a5170cac4094296937606fd318439f7f40dcb2c6b5a4f6059829e87b39eae61a40cc27ae22466f2c7b5cf78d7a2299aed6df7c5e69c80f450f979bfae39a5ed82343a02cc61e877079ee26b42b9afc01d1f60627b4bfbfe12a5", "0x676326af0980eeee7f6deeb6b77609df8bc847aa6e20c1f15bb070d8650c9427a4862b1e08fbed2f88ff18e1085c152ef80534b9dfd56a7c488c7068103e76ae730715997214d3c528515d572296941cf89250010b3bef7fbf175e55faeaf36f5746814ef94da60bdedfc8b8fd02434cd5122f56c5c36567a6a627e7cda8a36e90756e29cf8091465d140e5037bce8abc4f59b9160f580affb0845095071764754449fb485dd5ba1af", "0x2356ca087f69fe3fd129686b9406f448eb71bf04576cfb19e01731f541fb487409a7ac705b32de77511dc7952aa26980661cfc77d08a69e74eedeea60befe46af667b8c95b946c7535b3ac0c6210944a1f3804a7cf16c033adad01e6cddf29eee99db6245f3408db3dc77d32d83666535c60bbdcf79a251c5690fbb93830ec942607182fe0dd45739b9587fad72c98a8462f1fde205253b08b857d91a947192310df13a592f1417b78", Accept}, - {"0xefe0ed52aa48ac1954d289cddc48fe2fa9d2fd0a30ec80558d120df81dfd1bd5bdafc6db6c1be75408c8913667966a67eeae3d4660c51365cd126acbcff0896a242f998d6cdd12effe1519826eb869762835d33e30ecfa9fa1c3c26b8481d106e301cb9d7d53d5499fe7b38107e222de26cb2a5dd2cdba60dca3f8cfc35e512b5f4ba6429be53041a8fbcea34546b3562f20668d414d8025448b46fdcf2b6665ac6eab707642b5", "0x815178f225ffa7735b81058aeb7618db87d8e027b56d76dba76acfca305df3bf1039e86a2485d525894528", "0xe8cb702599322c16a07935ebaa175e1da2c090807209942f43df5c6db4732f08235da740218ce9ab2b654e53d8f102a0a4b0aca861270ca6788aebcd223d2ac3640ccdaa43aac14970751a6eafed7180a51a4d6de93b3e5e7e74f8a55bef5caf5a096e11354cae423d770fe1bc6682752b639e7510d7a2b77d44bf104c3333ce029d4f7e49255fd50e6ee2ba1002fc7c2c17b9f17053dc11135bc5b5e5f6e7cc075b3d0e658affc64b24819a3a8458a4467faa76112ffb6c061a96a199f2ef4f4e9a2b91687c7be85f009029c60495", "0x5437f7393e93182cc931add5c2ab61373c0a83a9c9713b91c0d880325cb6153a369feb6c2755c68f18444e1e67f0b16bcfba717c3b61833ae1c4a28b64b6860aaaf9fdebede0ee2e6aa88b18ac1e39ab5307678669de5d1046e800585adca7c560f923eb3511afccb3eb52c507a9e96a266aac75439b289a0756415f50658d07ff5ef236f3ffc6e5a57f4b5e27785737fbb77f4e0c780de0dbdafe2de14ec61344346ecd6f2db6cf6f0b12c95d7103f68fb837d022504a04f69a", Reject}, - {"0x5aaf78fa0137ed7a80a760cb1f00fe76f8dba1048bf35db85ed43d7081fff9c7fd61e71fe7a42ef861c081786d0b92053263a92d0491403f31bcddac325b7012d1078c19c17a16a22b57eed143f6d1aa3c7cb823479f8314a87db3142aaf50a8ec1eb8afec5c09bc5c1f97b5f617681ff9cafaf6b5bd6f186892e2016f58", "0xda431fbf1062b9ef1be8812d7d6870257f11aba4b9f27ce4f3db13200111a2e6862219042331d8e31c2438f9f6bc0dd77708200480d5c26632b9bac060daf4a4f74fd966fab0fcaea1853b3478eb6c3088b732a5ac20c0c13d5a3ae65fe23b", "0x57fb8a5ff255e23da812337e4145d4eaa11529de3894741886ae99a839bed9a10ae06719a0a820a34295a62e2534eaf0431b6be1b5187384dff144e828932622af0624976cb4b9660833385346cbc2d55379d0c72eda68a10202be3e8c92cc8d151864d2d465abc9ec6759f4f2e341cd4dcf4a4fac1ce4a480e065eaf859dff8799646bf9638535979cc8b616215b9c737d59bc0146520d415511aaef942a923afa58435d9d5", "0x05a08475905993424f0ce051bba9213855c74d601ed82089ec8f804b5e29275ec2b6b53ea813c1931a248418500a1a73e6c94a7a9f72df4cfd863218a928c999e8bb65106c606bc40e068b732e312b63b6ce5f6370402f9f576fe33d981ed9f06bcbc653aea90e3a2e7359560001e787119f8ee1d90695753582e52e077bd848c8c6eec421a2b79531fc15798c044ead4a81bc40b98964c9b21ff49c0a5da2d20752ca63a0d8", Accept}, - {"0x7afd6101ca03eee6db2ee5bd17c4df4645d3099c5b69d01efddd9656f14a5085534f1bbab0e9213e827715c5bd4abf8f9a7a1052cf1afb2b6332ec74c4b18e6a6ef976bfb70c2d", "0x33fe913d149938164862fe788a7dfaa901690376e3e193523fc92afc6e8e1ef4fb40ed01273231942a2b5b4d7d59b5e65b3397fa61c7453b1559b177b1b160fff8cf48867097e887c4be19a6c33ba156cae132090b4f8b7e54a501431a04f066b003ca2868e4cef065a1d1f5903ee581ac3c97003d71160fe3e643a42126c08e17c6b1675c8407bc6f3ad4ccb858535cbe132c8b48e9fbedcf2e222cec319a95a3c4f75df10463b11bd97e810c623c92ab8efe5d31f0d89ad85ac8", "0x757c4d7f4d108027363a6181eb0d950bc515afe7d7dd103cfadce2295030430840a45b4e541c4966e9f991ee219b26ace999b7a0d07d9e10414644daf591b09a04696705cc2555ec7c05dfc9e51d349ae25a96106f99a620d4962edae0b940c62276c6", "0x65fbf3319e294a7109a1f607c3379360f78df96c940b7a244c725a23cc632f4dd4c6283bddbe8dfb46c69de79dc337aea892708c5de1a27c6a422f41fce6ab5b19100de32081c2a066e51cacfbf5d8c76bed6a502ada2ff044619e3f5d196d401ba3a45cc8ebc8767750239ecf326b3eb658ef970baeefa40fd1e1dbcbdd7d6a7838d6a20595765021d5e3f8fe6a96c4a346f8a26990317de9c57a6a309a132a6b6dfad21c1d7f707e8607e497b7cca31b9d5bf804af4d46", Reject}, + {"0x01", "0x01", "0x", "0x00", 200, Panic}, // Modulo of 0 should panic + {"0x01", "0x01", "0x0000", "0x00", 200, Panic}, // Modulo of 0 should panic + {"0x54b7", "0x00", "0x01", "0x", 200, Accept}, + {"0x286e0b2a3fea08c786634bdf0a608fb22009c512e6f1f174", "0x9cebf0aae57f76408a", "0xcf5d2d1fdc2e3233adcc13c8b3fc2fb0a3d3c1032ee14288c9026968c59d6fd7f8c9ef82e63bea29304ebb91b150", "0x9e26c7578c46f09e26e67224526193f5af3512662276e54cb91944d9f80514b31fba2d4c6231c97309a79cfc09b0", 507, Accept}, + {"0xb04336dca137d1284edf958923d01c83f6a09e50bcfb1b509c2afe63bca4f64bf28a482f202cdf08e4fad627acde33c4a5206086641acf2ceab1669bf99b5d672dc71a5d2fc7ff99152f2ecb71e95543cb72be06151e3b75c12961773a0b20e59ceb18713ee7313cb3c146b10188a23de2dab3b733d2dbc4b30258e6e8cde85d1c394a76784a2038a0499feaf4851f22c48b30a7eedf02de934f8a31930d90426fd93241862614943e7a6e2e7f3ef9b08ce14030dcb8ca51d53743ac", "0x3bc794defa8e", "0xf418c1ba14622a93b40859b6fa5c8869ceeab204991a18bba8b414a03bab048c016a98c190ca7f4edb82745e8d91ce930b28c3e8c6f783ff6ea7cf4e092fe845d81189c8d77e4d6b2a3c967ed3d64a7310be13260589531e6485ddf9b065bed8142d7189fe22e213847bc0e10c5ff21e5f12c513f91357db5de6dc879f1e622dc386be6521f48cd476adb021050c09b913147ccb0c7e9ea2712f63b1c2273c4eb70267d366c8eb9548d3bcc19972dce8538767cd53d010e35a3bbab920afd498184d587f3f081fcc7018fd9ad448076a4a8ff231fc", "0x7d01fce371b80532a8ba65fc442e3adb4a5cae46d734258d342fbabaad7e83b14474fd21a5cee7e4a53f3de7e6f3c497b893f0cf23d9a743c4dfa736fb8080d54083a03b20f598ec1eed1d83714465914aa9171cdb1c3a56fb9c021e0c80f44a4d2b4b5c4e078fdc818474af5e0a334b25ac3f069d2dcc72dca335d05ac24fdbfabf07b17ce6e9fb996100509545bd9a0e5df48215112e04a68b2cc700b1a379e3a5df9d2913498cb8e15c92bec53a3c5775dd7fdfa9a5b515f738c88dc404b09cc2a4c389ee6334da58364d5c22482b905a1ec3fc", 2696, Accept}, + {"0x3e1c6d61105021cbd5388fbad1bd004929932619359415cbf63b2a5ba087a615ac387a710e19affd897f750581c815ab75c56ab0f7f43fe29ef0a2c10a582ee7cbf548a1e58d3be900f2edd57ecc3e3ce2543730a5b7241f640215", "0xa80794b876bc56a2031a0fe504ee9047dac05791fe78917dc82dc06bdeb519ce285713e9c3a97d4bbe065be9cdf6d7d845f0206bad7d23eace4856", "0x33f27976478080519dd19e89950d04b1e65f3e4bd5e684b234f68584c54415f2896440391e2b36a65bb3e3fafb10a9c6ffae6c5b8ce5223bf786fa0a7a3a6d5a54985f26936fdbc70b2b94790d712de3ed0ecf34332e805da31224f83041efa739e958634529d94f8bd4c64d39a8e3e3d2741623912d97c33751aa0d", "0x2d6f597bb2771b5e9eafeeebb220a157d9bc7a7acb3eb0fed18272da51d1abef322e4b85b02c7ac79bddae7ac8708cc7f01e774e8e8b87023374567b52c3f8e9df28063abfdcb19152d95e2b6b3077acfb687e45e32164c132b0931c587eaa3f34ac474ec0512c6b57bad2b98ef83dca85d23a7c9b114893170501f2", 10363, Accept}, + {"0x4de679ab106df6431f37cb20e60491eab2a00fda0017e3788856589e332db9596eda1ec03ea4e641ae4b22e7923662537ddd4ae130148ecd193b5e4578d7409e5371b50f45e92293d8c786b824eb26dd6c31419f8ad6383327772cd10b84b40d10a7438c1b3a92aedb718a0c97137e1064ad67484d7206487902ef8f8b7a34318474ba0f6113e9dc15c4e30e7711f641a82f6672ad2e039a09228db6db2287", "0xd021d1d6cc99274c090b16afe3a1c4314f48316dcd2a2cdebaaa2896c51c9f3d779bd7be01a2fdc17093c2c9a633", "0xb7a91bb84e0abaef90b4d4293d0c4968a2", "0x62c668fb320f44c7fec283e7827a6ce1ff", 12083, Accept}, + {"0x51ebd23d2a02f976d3d9aae2061e06a8c0452b4b556443606ade0c71ea57a8463bbad81a5d6312237f8ab6194e18feb808631d40318b608cb7fe876d3ded24f04bbddc053a3be4579f5c6cdadc3ed1192a5016c609ff80a76677ed214ed0e5e04bf70bc03b6c15b999c4d343466b0324fa5a0a42ad60885885ab43f928991f30783819caba87e247837b0948b1d8d050ed", "0x1fbe100e76befa9e13", "0x576df8720f308d6e342644063415492caa9d4a11c80030e25f7541e56e62869d15b08a8807d789870194b0c7a325cf9d13e49c654b08965c8eb3e144145fb7", "0x197bcf7eafab09fa4776dbaa9ebb8cc2ff6787d1a800819cd75f507a1372157085dc171f6e501edf2b44d46038d3fa49e0db8ebac4b41461bdce184585edd9", 2200, Accept}, + {"0x9c61f9e2209144eeabc02cb02e5db1484544e33478eb374a18be5baf71b16e91d9ab86882984ea9ba16fde77eb0ef161c497c1883e0cbdb8dca844ad7b8f270073ab640c385e4f9512", "0x648110c896453b6f1a3a0b234f5c0f8b7c4b4d958458280372a6232f9d98cd1420df6a5691fa1bf773f6bd", "0xe5e14e935f795ad814f54d95248b0102b2b0c351e8a5112541343c024d90dfa43c702eea820354a2670563425ee515c4dcc2c6bed73234b0e77384f3ba64a1b8b068149b2363566cdf9c80af", "0xa1d077b5157b4e829c814a0e8fb7e9b83e30e65ff46d3264dc619063a2de57fb171e050c5ec85715b73a8a8a7d2b155a6a77855edea62c9a6850c8dec1551bde227304b7df2811245405fdd5", 3535, Accept}, + {"0xe1b779ff6951aee456aeaf87a963678eaaae4ed61f387b68e4f196ff71440a5955b9a8c2144dbe4c00717b157564f21b54c8c3934bb43754af039068ba03d1ab7c53f9d5526842cb", "0x6bc12883963b0f0b6eb6c275bcc9", "0x072c23cab0e4dbc633b86e45a6b9bdfaf87076bf618c08b142d42b7ad8c3ea4795e873dad518ace0f9e84a4e265191972e303bfbbd6cff781de09a1ccb19f0dc5d874dfc3b89bfa666b391068c3dc9c183f04e4dcd1ec80ed92fd4c792e102904817a41ae1208ed39a9484d61e10491859924a0a04a9455e36458702dcd8a312176e9a05e0e45a14783ecaa7e93f410a8a51848ad706d014467d634fa7c0d6756f54e5f980", "0x06d4a5ffa4568bf3bc20ff29f74941b212ec9121d936d6becbfde46dca5034e0749fead5293e42331a922d1e6a64efc42bf165ca3853c2a80248d32fdf70a6c233ef32851b85ea1c1b51ca364dd2bcd9f25a6249c014dc36b123382099f5f060eb8c0b6d13e4facb932fa49ae140b917dad9e82076e71b407928405aa449fb66eacd97429296a8f8d3cafd8660d124f5d98e6fdb9f1a74ba10a76b724bb8ef4ec98c749b6b", 4041, Accept}, + {"0x4594ea63dd8b77f34701aaae1f430d4adee9811213bde681fd750cd4bff65322654553180248e580de54da02365dbcc61ad6039a61c0c5783872038cccf618ce10757b50d4f58529cc2d6d9ca30543e8ddedc481757a679101", "0xd32aab68fadf838e361d75da2ce241dd0b95dd38e3ceb860975e39d4eab04e84581269d22dc8880395c6c091b3859cd9fa031186af5bc0f23d6ada8fbfae9f7dcc307d862c", "0x7b646597ae005c1b0c2bc981917294e669a47fc12b27d08c1741caa5d31c68", "0x317c66d1e4a6e22d60a1299aaec61f9e8668e08bb94b11e59e32d1daad8e11", 7122, Accept}, + {"0x44dfe16a0cc499362a5a6b6b5d4167b9e45c3bbd1b98b494e99ff71010013a8c816816f112a69f9e70a320625c149555e1276bad70999da1b3c124e5c54cbeb02b534f845ffdfcede15b01fa8d0bd8f22b95ace6cf5d0aa97cb81f1688afecef51cc48fdf3155185090e8249795af2c26997ea1a915fd85b5a8bf9cce7c7dbbb6f268cd424e6b86331d32a6e4cf783957160", "0xc392b4bfe312f474a02d0860823a05a8a6d5846f1db0a9245a1f64cb354b5ab91590d24ebba8ef68a369d25932b1acfcb33b6af52a260313bcc0493c", "0x5492af9556e685fd639f80e42fae3e0cc4588233f4683017d376c5746b3eea", "0x4e13bec8183024e881e1688458437e0a3c49959c3099329c4540c0b5840a70", 13688, Accept}, + {"0x2ea1312db704ff29e0", "0x038302a78381a38adcb7581cbeb7a0797289d82d14a85cf4c36df72c5b5c3d464c4a280f930a85ef4aefb54ce935d01a18afd42d9a679140a360f2b185ac37fde9890d2808a6675e3d73bc696921babefa9cb1985b948e65734fae0515f0e6b7ef782bef9f1a4921c5df3e340e764bf6c347614c5649e645f3bdaaa2c7dbcc16b5107056", "0x71166d7a0b32f8cbd2f682474b61c5535e2867562bcf5dd5e43d2a4e036b78e871b18145e6da2ef327da994965ade4bb985f4f2402da936a6f90d0913512add104dc10741c06b948e911b8fbe9", "0x4540d8df3bc9cd82ff6e431440f65fd58165a43783dccabc315f5a33fa3a581068ca5ae3ede591e302fc863eff657b962d0e671235fc97456439921ec9023eff5b8256b056eb47eae5911f2e6b", 10658, Accept}, + {"0x1f206df741a36c542fb5e609c9299e62a96ee677ca7266d85d086d4ebd6ab9b52c56539c41b0a1a69a0a5dfc794cd6076360643660147c053f821992bf5c787a1fed53eab8f61e0d538aa3a352616774d419c7be55415e60a86f296d1baa199284ebd2ff12eb2b84a7dfedbe1d34efd3219265f302b91963416e42145bfbdf7d0132b1d32c98129521a61d92e2318f94b87f96f68eefe5263717999ab1780f9c15e895a5c188e47518b209f61c3a501e315c4ea0504de653d9b3f9d25658c1c30b99fa6b2a02ff99838d04b86bbeb13ca94d90fd96aca7eae17bc76cf13e33cf37769ad7bf98c6f151c3961d2157aa63ebd577f2f5dbb67805df9a649942843c", "0x37c463", "0x8eb38552534a9ca188412677f154eeba8f011cf6ae00472dcca54c068d57825ff7f703b1a8380d2fc9a7e1e142f8770a7da52e2d47638853aacbe450a80f2c35a9ce0e5feca7bfff871252ec2c5754cafdcde3cd20ce4767c23042570d3d9641e8517ea4c3f10d7f4ea927824d948aed87de2b856347faba08be786ad3d9f30cd1bc4b036dd4a0053c59d11fc2840aefde47222a0273323f45b08539313de7393d24ade84f8f57c719986db04a0f3f483375e5779c8b8ce913991a80ea6cb368bb3f1f2c3dc3d424d7c0ae607c6d052dc7b0ae170250e1ad10e6b327857cb8610904c526d51430c31931d4ba3d5ebab8d6321c48d6d482f5b129f69871f4405f", "0x1d6e8af1caa1098ce2429e32eb831598f6b28a65376e54fe863283b545949586e2f3b41285d6047fcd52d164be131325f80412d2ca8bb84dd945ae69b3e1bc4fa861905b1f3032ea7279d2ed3c03f78ece1c0d0f159e0a4776d1ee47516e4379105491c37d6bc86bc26420966076d114f5a4091e800259f59073fd5f7c0100fbcbc10a9f7cef6fcd03c04ae97b54994ea479e168bc00ae9ea84ad07497aa470d3d438ccfa669de5d99ccf36a2ab1773378101123f5bcdd9a6f5a1df889b8a0bbc071d692d68b69801cfa467bdcb8d00dc5f32be5ca907433667691527534c229701ec929ef836c7caef7a088205082f98a08860ed72d383e6ac256aa3680f3c6", 1884, Accept}, + {"0x7c391cf4e56c7c104d90177402b2e1a0f9179a06304f4357e4b146e116cd12e0f1c12bfc66171b8c8be104d09c304c340e125c4b6fda63b94315d74ad0e8b8178edac81b475da5dc7e825c309a4c0b5fb3c3e0bd7f94dc661cd8ac546940779e54edf58c6ace5589914541935bc66fff64442d8bc2e6dc8420257c8ab0a877729fe8", "0x74d69cdea330c38633c7bca9fb46d2e1e2050e5220c5fa3194584c62b4ebd3e85a70fd2f994d04681fc8aa32e580f87484b78ff8d3bab0412874e55772411288f4a6196f9da6db7aaebbf0d62e4e42275dfa475ac35802d912aacfb4f77e945f4e5e3c28610ddbd479280df848cd57829746fcc6452a5d4127b4f8b27a3149bc", "0x9000b0b587f64e78f51645a75d98b64d7fa1001d1636bcae53ea41f9f955f67f79c442adbca55d59c61642ed91364feef5e5147ed229cd5ff1d31b6c333a65f95e80c576f11ce4790c3162c351bd7df796c6e2184a387edea127c6ddf46a6eae6ade4066de609d655832b98b", "0x810f16edd6ffee0cad631b2f59ad6b3847f80974ce4376353ad1f8f487dae65e93ddb9552cc93b0725acb1ba3551132c138ef730568c3fde71918608edf3f78130170124d0a4d3d28fcd2cefb256465eb18e80ea0576fd1df44e76786a450285a0eef852b7df639925795293", 24014, Accept}, + {"0x9b7e403f0d0134635f90d344dbce30ac511e8e5e274a3436ccb75503d0ee72a3ba59c2a9b774ee74abe082e09702c65151186706c62200241d306d8cb18b40278c885222db5d001aecceff20e4be25ed83d4ff7d40c4c6e513a63238a5c07e45da3a24868caa67fae36047d955a648dd1c741284cdb8bc282c01b9d66d2c5b651268ff1d50356f1dc6be6d59814d7787e6", "0x30c54b", "0x093fd6b228d5d2268a36b0a1b8fb7dbcb4669c22e0cc2a5deaa3c3da890c5fa23dc0", "0x2a3d94206458cce1a0cee7ef45b3812de4f2ae4ee9b347acf55385eca217159f6b76b7c14774aa54e9667bb172d66b25d907682576a2ec7f2038c07e4f", 866, Panic}, } for _, modexpTestVector := range modexpTestVectors { @@ -5152,9 +5158,12 @@ func TestBytesModExp(t *testing.T) { byte %s byte %s bmodexp - byte %s -==`, modexpTestVector.Base, modexpTestVector.Exponent, modexpTestVector.Modulus, modexpTestVector.Result) +== +assert +global OpcodeBudget +int %d +==`, modexpTestVector.Base, modexpTestVector.Exponent, modexpTestVector.Modulus, modexpTestVector.Result, testLogicBudget-7-modexpTestVector.LogicCost) switch modexpTestVector.TestOutcome { case Accept: testAccepts(t, progText, 11) diff --git a/data/transactions/logic/opcodes.go b/data/transactions/logic/opcodes.go index 5f9639e048..74906d60f7 100644 --- a/data/transactions/logic/opcodes.go +++ b/data/transactions/logic/opcodes.go @@ -19,6 +19,7 @@ package logic import ( "cmp" "fmt" + "math" "strconv" "strings" @@ -85,15 +86,41 @@ const spOpcodesVersion = 11 // falcon_verify, sumhash512 // Unlimited Global Storage opcodes const boxVersion = 8 // box_* +// CustomCost encapsulates a custom cost function and its documentation, applicable to opcodes like bmodexp where linearCost is inadequate by itself +type CustomCost struct { + compute func(stack []stackValue, depth int) int + docCost string +} + +// Custom cost definition for bmodexp +func bmodExpCostFunction(stack []stackValue, depth int) int { + last := len(stack) - depth - 1 // mod + prev := last - depth - 1 // exp + pprev := last - depth - 2 // base + + expLength := float64(len(stack[prev].Bytes)) + modLength := float64(len(stack[last].Bytes)) + baseLength := float64(len(stack[pprev].Bytes)) + cost := (math.Pow(math.Max(baseLength, modLength), 1.63) * expLength / 15) + 200 + + return int(cost) +} + +var bmodexpCustomCost = &CustomCost{ + compute: bmodExpCostFunction, + docCost: "((len(B) * max(len(A), len(C)) ^ 1.63) / 15) + 200", +} + type linearCost struct { - baseCost int - chunkCost int - chunkSize int - depth int + baseCost int + chunkCost int + chunkSize int + depth int + customCost *CustomCost } func (lc linearCost) check() linearCost { - if lc.baseCost < 1 || lc.chunkCost < 0 || lc.chunkSize < 0 || lc.chunkSize > maxStringSize || lc.depth < 0 { + if (lc.customCost == nil && lc.baseCost < 1) || lc.chunkCost < 0 || lc.chunkSize < 0 || lc.chunkSize > maxStringSize || lc.depth < 0 { panic(fmt.Sprintf("bad cost configuration %+v", lc)) } if lc.chunkCost > 0 && lc.chunkSize == 0 { @@ -102,10 +129,19 @@ func (lc linearCost) check() linearCost { if lc.chunkCost == 0 && lc.chunkSize > 0 { panic(fmt.Sprintf("no chunk cost with positive chunk size %+v", lc)) } + if lc.customCost != nil && lc.customCost.compute == nil { + panic(fmt.Sprintf("CustomCost exists without a non-nil compute function pointer value %+v", lc)) + } + if lc.customCost != nil && lc.customCost.docCost == "" { + panic(fmt.Sprintf("CustomCost exists without a value for docCost %+v", lc)) + } return lc } func (lc *linearCost) compute(stack []stackValue) int { + if lc.customCost != nil { + return lc.customCost.compute(stack, lc.depth) + } cost := lc.baseCost if lc.chunkCost != 0 && lc.chunkSize != 0 { // Uses basics.DivCeil rather than (count/chunkSize) to match how Ethereum discretizes hashing costs. @@ -116,6 +152,9 @@ func (lc *linearCost) compute(stack []stackValue) int { } func (lc *linearCost) docCost(argLen int) string { + if lc.customCost != nil { + return lc.customCost.docCost + } if *lc == (linearCost{}) { return "" } @@ -240,6 +279,15 @@ func (d OpDetails) costs(cost int) OpDetails { return d } +func defaultCustomCost(customCost *CustomCost) OpDetails { + return detDefault().customCost(customCost) +} + +func (d OpDetails) customCost(customCost *CustomCost) OpDetails { + d.FullCost = linearCost{customCost: customCost}.check() + return d +} + func only(m RunMode) OpDetails { d := detDefault() d.Modes = m @@ -334,7 +382,7 @@ func costByFieldAndLength(immediate string, group *FieldGroup, costs []linearCos func costByLength(initial, perChunk, chunkSize, depth int) OpDetails { d := detDefault() - d.FullCost = linearCost{initial, perChunk, chunkSize, depth}.check() + d.FullCost = linearCost{baseCost: initial, chunkCost: perChunk, chunkSize: chunkSize, depth: depth}.check() return d } @@ -798,7 +846,7 @@ var OpSpecs = []OpSpec{ costByField("g", &EcGroups, []int{ BN254g1: 630, BN254g2: 3_300, BLS12_381g1: 1_950, BLS12_381g2: 8_150})}, - {0xe6, "bmodexp", opBytesModExp, proto("bbb:b"), 11, costly(2000)}, // TODO: refine cost model for bmodexp + {0xe6, "bmodexp", opBytesModExp, proto("bbb:b"), 11, defaultCustomCost(bmodexpCustomCost)}, } // OpcodesByVersion returns list of opcodes available in a specific version of TEAL From 468210e44adbd29a6dca7acc2d342707eb8cb2b4 Mon Sep 17 00:00:00 2001 From: mangoplane <104189015+mangoplane@users.noreply.github.com> Date: Fri, 25 Oct 2024 21:43:55 +1100 Subject: [PATCH 5/5] refactor: Move bmodexp cost magic numbers to constants and improve comments --- data/transactions/logic/opcodes.go | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/data/transactions/logic/opcodes.go b/data/transactions/logic/opcodes.go index 74906d60f7..3fc4eb3b91 100644 --- a/data/transactions/logic/opcodes.go +++ b/data/transactions/logic/opcodes.go @@ -86,7 +86,8 @@ const spOpcodesVersion = 11 // falcon_verify, sumhash512 // Unlimited Global Storage opcodes const boxVersion = 8 // box_* -// CustomCost encapsulates a custom cost function and its documentation, applicable to opcodes like bmodexp where linearCost is inadequate by itself +// CustomCost encapsulates a custom cost function and its documentation, +// applicable to opcodes like bmodexp where linearCost is inadequate by itself type CustomCost struct { compute func(stack []stackValue, depth int) int docCost string @@ -98,10 +99,19 @@ func bmodExpCostFunction(stack []stackValue, depth int) int { prev := last - depth - 1 // exp pprev := last - depth - 2 // base + // Empirically estimated cost function constants + const ( + exponentFactor = 1.63 // Adjusts cost of base & mod multiplication in the modexp by squaring algorithm + scalingFactor = 15 // Normalization factor + baseCost = 200 // Minimum cost of bmodexp + ) + expLength := float64(len(stack[prev].Bytes)) modLength := float64(len(stack[last].Bytes)) baseLength := float64(len(stack[pprev].Bytes)) - cost := (math.Pow(math.Max(baseLength, modLength), 1.63) * expLength / 15) + 200 + + // Derived from the asymptotic time complexity of the exponentiation by squaring algorithm + cost := (math.Pow(math.Max(baseLength, modLength), exponentFactor) * expLength / scalingFactor) + baseCost return int(cost) }