diff options
Diffstat (limited to 'data/transactions/logic/assembler.go')
-rw-r--r-- | data/transactions/logic/assembler.go | 383 |
1 files changed, 198 insertions, 185 deletions
diff --git a/data/transactions/logic/assembler.go b/data/transactions/logic/assembler.go index b7a6018e5..cdf91df68 100644 --- a/data/transactions/logic/assembler.go +++ b/data/transactions/logic/assembler.go @@ -247,14 +247,6 @@ type OpStream struct { HasStatefulOps bool } -// GetVersion returns the LogicSigVersion we're building to -func (ops *OpStream) GetVersion() uint64 { - if ops.Version == 0 { - ops.Version = AssemblerDefaultVersion - } - return ops.Version -} - // createLabel inserts a label reference to point to the next // instruction, reporting an error for a duplicate. func (ops *OpStream) createLabel(label string) { @@ -437,7 +429,7 @@ func assembleIntC(ops *OpStream, spec *OpSpec, args []string) error { if len(args) != 1 { return ops.error("intc operation needs one argument") } - constIndex, err := strconv.ParseUint(args[0], 0, 64) + constIndex, err := simpleImm(args[0], "constant") if err != nil { return ops.error(err) } @@ -448,7 +440,7 @@ func assembleByteC(ops *OpStream, spec *OpSpec, args []string) error { if len(args) != 1 { return ops.error("bytec operation needs one argument") } - constIndex, err := strconv.ParseUint(args[0], 0, 64) + constIndex, err := simpleImm(args[0], "constant") if err != nil { return ops.error(err) } @@ -738,7 +730,7 @@ func assembleArg(ops *OpStream, spec *OpSpec, args []string) error { if len(args) != 1 { return ops.error("arg operation needs one argument") } - val, err := strconv.ParseUint(args[0], 0, 64) + val, err := simpleImm(args[0], "argument") if err != nil { return ops.error(err) } @@ -786,20 +778,42 @@ func assembleSubstring(ops *OpStream, spec *OpSpec, args []string) error { return nil } -func assembleTxn(ops *OpStream, spec *OpSpec, args []string) error { - if len(args) != 1 { - return ops.error("txn expects one argument") - } - fs, ok := txnFieldSpecByName[args[0]] +func txnFieldImm(name string, expectArray bool, ops *OpStream) (*txnFieldSpec, error) { + fs, ok := TxnFieldSpecByName[name] if !ok { - return ops.errorf("txn unknown field: %#v", args[0]) + return nil, fmt.Errorf("unknown field: %#v", name) } - _, ok = txnaFieldSpecByField[fs.field] - if ok { - return ops.errorf("found array field %#v in txn op", args[0]) + if expectArray != fs.array { + if expectArray { + return nil, fmt.Errorf("found scalar field %#v while expecting array", name) + } + return nil, fmt.Errorf("found array field %#v while expecting scalar", name) } if fs.version > ops.Version { - return ops.errorf("field %#v available in version %d. Missed #pragma version?", args[0], fs.version) + return nil, + fmt.Errorf("field %#v available in version %d. Missed #pragma version?", name, fs.version) + } + return &fs, nil +} + +func simpleImm(value string, label string) (uint64, error) { + res, err := strconv.ParseUint(value, 0, 64) + if err != nil { + return 0, fmt.Errorf("unable to parse %s %#v as integer", label, value) + } + if res > 255 { + return 0, fmt.Errorf("%s beyond 255: %d", label, res) + } + return res, err +} + +func assembleTxn(ops *OpStream, spec *OpSpec, args []string) error { + if len(args) != 1 { + return ops.error("txn expects one argument") + } + fs, err := txnFieldImm(args[0], false, ops) + if err != nil { + return ops.errorf("%s %w", spec.Name, err) } ops.pending.WriteByte(spec.Opcode) ops.pending.WriteByte(uint8(fs.field)) @@ -823,23 +837,13 @@ func assembleTxna(ops *OpStream, spec *OpSpec, args []string) error { if len(args) != 2 { return ops.error("txna expects two immediate arguments") } - fs, ok := txnFieldSpecByName[args[0]] - if !ok { - return ops.errorf("txna unknown field: %#v", args[0]) - } - _, ok = txnaFieldSpecByField[fs.field] - if !ok { - return ops.errorf("txna unknown field: %#v", args[0]) - } - if fs.version > ops.Version { - return ops.errorf("txna %#v available in version %d. Missed #pragma version?", args[0], fs.version) - } - arrayFieldIdx, err := strconv.ParseUint(args[1], 0, 64) + fs, err := txnFieldImm(args[0], true, ops) if err != nil { - return ops.error(err) + return ops.errorf("%s %w", spec.Name, err) } - if arrayFieldIdx > 255 { - return ops.errorf("txna array index beyond 255: %d", arrayFieldIdx) + arrayFieldIdx, err := simpleImm(args[1], "array index") + if err != nil { + return ops.errorf("%s %w", spec.Name, err) } ops.pending.WriteByte(spec.Opcode) @@ -853,16 +857,9 @@ func assembleTxnas(ops *OpStream, spec *OpSpec, args []string) error { if len(args) != 1 { return ops.error("txnas expects one immediate argument") } - fs, ok := txnFieldSpecByName[args[0]] - if !ok { - return ops.errorf("txnas unknown field: %#v", args[0]) - } - _, ok = txnaFieldSpecByField[fs.field] - if !ok { - return ops.errorf("txnas unknown field: %#v", args[0]) - } - if fs.version > ops.Version { - return ops.errorf("txnas %#v available in version %d. Missed #pragma version?", args[0], fs.version) + fs, err := txnFieldImm(args[0], true, ops) + if err != nil { + return ops.errorf("%s %w", spec.Name, err) } ops.pending.WriteByte(spec.Opcode) @@ -875,24 +872,13 @@ func assembleGtxn(ops *OpStream, spec *OpSpec, args []string) error { if len(args) != 2 { return ops.error("gtxn expects two arguments") } - slot, err := strconv.ParseUint(args[0], 0, 64) + slot, err := simpleImm(args[0], "transaction index") if err != nil { - return ops.error(err) - } - if slot > 255 { - return ops.errorf("%s transaction index beyond 255: %d", spec.Name, slot) + return ops.errorf("%s %w", spec.Name, err) } - - fs, ok := txnFieldSpecByName[args[1]] - if !ok { - return ops.errorf("%s unknown field: %#v", spec.Name, args[1]) - } - _, ok = txnaFieldSpecByField[fs.field] - if ok { - return ops.errorf("found array field %#v in %s op", args[1], spec.Name) - } - if fs.version > ops.Version { - return ops.errorf("field %#v available in version %d. Missed #pragma version?", args[1], fs.version) + fs, err := txnFieldImm(args[1], false, ops) + if err != nil { + return ops.errorf("%s %w", spec.Name, err) } ops.pending.WriteByte(spec.Opcode) @@ -917,31 +903,17 @@ func assembleGtxna(ops *OpStream, spec *OpSpec, args []string) error { if len(args) != 3 { return ops.errorf("%s expects three arguments", spec.Name) } - slot, err := strconv.ParseUint(args[0], 0, 64) + slot, err := simpleImm(args[0], "transaction index") if err != nil { - return ops.error(err) - } - if slot > 255 { - return ops.errorf("%s group index beyond 255: %d", spec.Name, slot) - } - - fs, ok := txnFieldSpecByName[args[1]] - if !ok { - return ops.errorf("%s unknown field: %#v", spec.Name, args[1]) + return ops.errorf("%s %w", spec.Name, err) } - _, ok = txnaFieldSpecByField[fs.field] - if !ok { - return ops.errorf("%s unknown field: %#v", spec.Name, args[1]) - } - if fs.version > ops.Version { - return ops.errorf("%s %#v available in version %d. Missed #pragma version?", spec.Name, args[1], fs.version) - } - arrayFieldIdx, err := strconv.ParseUint(args[2], 0, 64) + fs, err := txnFieldImm(args[1], true, ops) if err != nil { - return ops.error(err) + return ops.errorf("%s %w", spec.Name, err) } - if arrayFieldIdx > 255 { - return ops.errorf("%s array index beyond 255: %d", spec.Name, arrayFieldIdx) + arrayFieldIdx, err := simpleImm(args[2], "array index") + if err != nil { + return ops.errorf("%s %w", spec.Name, err) } ops.pending.WriteByte(spec.Opcode) @@ -956,25 +928,13 @@ func assembleGtxnas(ops *OpStream, spec *OpSpec, args []string) error { if len(args) != 2 { return ops.errorf("%s expects two immediate arguments", spec.Name) } - - slot, err := strconv.ParseUint(args[0], 0, 64) + slot, err := simpleImm(args[0], "transaction index") if err != nil { - return ops.error(err) + return ops.errorf("%s %w", spec.Name, err) } - if slot > 255 { - return ops.errorf("%s group index beyond 255: %d", spec.Name, slot) - } - - fs, ok := txnFieldSpecByName[args[1]] - if !ok { - return ops.errorf("%s unknown field: %#v", spec.Name, args[1]) - } - _, ok = txnaFieldSpecByField[fs.field] - if !ok { - return ops.errorf("%s unknown field: %#v", spec.Name, args[1]) - } - if fs.version > ops.Version { - return ops.errorf("%s %#v available in version %d. Missed #pragma version?", spec.Name, args[1], fs.version) + fs, err := txnFieldImm(args[1], true, ops) + if err != nil { + return ops.errorf("%s %w", spec.Name, err) } ops.pending.WriteByte(spec.Opcode) @@ -992,16 +952,9 @@ func assembleGtxns(ops *OpStream, spec *OpSpec, args []string) error { if len(args) != 1 { return ops.errorf("%s expects one or two immediate arguments", spec.Name) } - fs, ok := txnFieldSpecByName[args[0]] - if !ok { - return ops.errorf("%s unknown field: %#v", spec.Name, args[0]) - } - _, ok = txnaFieldSpecByField[fs.field] - if ok { - return ops.errorf("found array field %#v in gtxns op", args[0]) - } - if fs.version > ops.Version { - return ops.errorf("field %#v available in version %d. Missed #pragma version?", args[0], fs.version) + fs, err := txnFieldImm(args[0], false, ops) + if err != nil { + return ops.errorf("%s %w", spec.Name, err) } ops.pending.WriteByte(spec.Opcode) @@ -1014,23 +967,13 @@ func assembleGtxnsa(ops *OpStream, spec *OpSpec, args []string) error { if len(args) != 2 { return ops.errorf("%s expects two immediate arguments", spec.Name) } - fs, ok := txnFieldSpecByName[args[0]] - if !ok { - return ops.errorf("%s unknown field: %#v", spec.Name, args[0]) - } - _, ok = txnaFieldSpecByField[fs.field] - if !ok { - return ops.errorf("%s unknown field: %#v", spec.Name, args[0]) - } - if fs.version > ops.Version { - return ops.errorf("%s %#v available in version %d. Missed #pragma version?", spec.Name, args[0], fs.version) - } - arrayFieldIdx, err := strconv.ParseUint(args[1], 0, 64) + fs, err := txnFieldImm(args[0], true, ops) if err != nil { - return ops.error(err) + return ops.errorf("%s %w", spec.Name, err) } - if arrayFieldIdx > 255 { - return ops.errorf("%s array index beyond 255: %d", spec.Name, arrayFieldIdx) + arrayFieldIdx, err := simpleImm(args[1], "array index") + if err != nil { + return ops.errorf("%s %w", spec.Name, err) } ops.pending.WriteByte(spec.Opcode) ops.pending.WriteByte(uint8(fs.field)) @@ -1043,16 +986,9 @@ func assembleGtxnsas(ops *OpStream, spec *OpSpec, args []string) error { if len(args) != 1 { return ops.errorf("%s expects one immediate argument", spec.Name) } - fs, ok := txnFieldSpecByName[args[0]] - if !ok { - return ops.errorf("%s unknown field: %#v", spec.Name, args[0]) - } - _, ok = txnaFieldSpecByField[fs.field] - if !ok { - return ops.errorf("%s unknown field: %#v", spec.Name, args[0]) - } - if fs.version > ops.Version { - return ops.errorf("%s %#v available in version %d. Missed #pragma version?", spec.Name, args[0], fs.version) + fs, err := txnFieldImm(args[0], true, ops) + if err != nil { + return ops.errorf("%s %w", spec.Name, err) } ops.pending.WriteByte(spec.Opcode) ops.pending.WriteByte(uint8(fs.field)) @@ -1076,17 +1012,11 @@ func asmItxnOnly(ops *OpStream, spec *OpSpec, args []string) error { if len(args) != 1 { return ops.errorf("%s expects one argument", spec.Name) } - fs, ok := txnFieldSpecByName[args[0]] - if !ok { - return ops.errorf("%s unknown field: %#v", spec.Name, args[0]) - } - _, ok = txnaFieldSpecByField[fs.field] - if ok { - return ops.errorf("found array field %#v in %s op", args[0], spec.Name) - } - if fs.version > ops.Version { - return ops.errorf("field %#v available in version %d. Missed #pragma version?", args[0], fs.version) + fs, err := txnFieldImm(args[0], false, ops) + if err != nil { + return ops.errorf("%s %w", spec.Name, err) } + ops.pending.WriteByte(spec.Opcode) ops.pending.WriteByte(uint8(fs.field)) ops.returns(fs.ftype) @@ -1097,26 +1027,74 @@ func asmItxna(ops *OpStream, spec *OpSpec, args []string) error { if len(args) != 2 { return ops.errorf("%s expects two immediate arguments", spec.Name) } - fs, ok := txnFieldSpecByName[args[0]] - if !ok { - return ops.errorf("%s unknown field: %#v", spec.Name, args[0]) + fs, err := txnFieldImm(args[0], true, ops) + if err != nil { + return ops.errorf("%s %w", spec.Name, err) } - _, ok = txnaFieldSpecByField[fs.field] - if !ok { - return ops.errorf("%s unknown field: %#v", spec.Name, args[0]) + arrayFieldIdx, err := simpleImm(args[1], "array index") + if err != nil { + return ops.errorf("%s %w", spec.Name, err) } - if fs.version > ops.Version { - return ops.errorf("%s %#v available in version %d. Missed #pragma version?", spec.Name, args[0], fs.version) + + ops.pending.WriteByte(spec.Opcode) + ops.pending.WriteByte(uint8(fs.field)) + ops.pending.WriteByte(uint8(arrayFieldIdx)) + ops.returns(fs.ftype) + return nil +} + +// asmGitxn delegates to asmGitxnOnly or asmGitxna depending on number of operands +func asmGitxn(ops *OpStream, spec *OpSpec, args []string) error { + if len(args) == 2 { + return asmGitxnOnly(ops, spec, args) + } + if len(args) == 3 { + itxna := OpsByName[ops.Version]["gitxna"] + return asmGitxna(ops, &itxna, args) + } + return ops.errorf("%s expects two or three arguments", spec.Name) +} + +func asmGitxnOnly(ops *OpStream, spec *OpSpec, args []string) error { + if len(args) != 2 { + return ops.errorf("%s expects two arguments", spec.Name) } - arrayFieldIdx, err := strconv.ParseUint(args[1], 0, 64) + slot, err := simpleImm(args[0], "transaction index") if err != nil { - return ops.error(err) + return ops.errorf("%s %w", spec.Name, err) } - if arrayFieldIdx > 255 { - return ops.errorf("%s array index beyond 255: %d", spec.Name, arrayFieldIdx) + fs, err := txnFieldImm(args[1], false, ops) + if err != nil { + return ops.errorf("%s %w", spec.Name, err) } ops.pending.WriteByte(spec.Opcode) + ops.pending.WriteByte(uint8(slot)) + ops.pending.WriteByte(uint8(fs.field)) + ops.returns(fs.ftype) + return nil +} + +func asmGitxna(ops *OpStream, spec *OpSpec, args []string) error { + if len(args) != 3 { + return ops.errorf("%s expects three immediate arguments", spec.Name) + } + slot, err := simpleImm(args[0], "transaction index") + if err != nil { + return ops.errorf("%s %w", spec.Name, err) + } + + fs, err := txnFieldImm(args[1], true, ops) + if err != nil { + return ops.errorf("%s %w", spec.Name, err) + } + arrayFieldIdx, err := simpleImm(args[2], "array index") + if err != nil { + return ops.errorf("%s %w", spec.Name, err) + } + + ops.pending.WriteByte(spec.Opcode) + ops.pending.WriteByte(uint8(slot)) ops.pending.WriteByte(uint8(fs.field)) ops.pending.WriteByte(uint8(arrayFieldIdx)) ops.returns(fs.ftype) @@ -1127,7 +1105,7 @@ func assembleGlobal(ops *OpStream, spec *OpSpec, args []string) error { if len(args) != 1 { return ops.errorf("%s expects one argument", spec.Name) } - fs, ok := globalFieldSpecByName[args[0]] + fs, ok := GlobalFieldSpecByName[args[0]] if !ok { return ops.errorf("%s unknown field: %#v", spec.Name, args[0]) } @@ -1139,7 +1117,7 @@ func assembleGlobal(ops *OpStream, spec *OpSpec, args []string) error { val := fs.field ops.pending.WriteByte(spec.Opcode) ops.pending.WriteByte(uint8(val)) - ops.trace("%s (%s)", fs.field.String(), fs.ftype.String()) + ops.trace("%s (%s)", fs.field, fs.ftype) ops.returns(fs.ftype) return nil } @@ -1148,7 +1126,7 @@ func assembleAssetHolding(ops *OpStream, spec *OpSpec, args []string) error { if len(args) != 1 { return ops.errorf("%s expects one argument", spec.Name) } - fs, ok := assetHoldingFieldSpecByName[args[0]] + fs, ok := AssetHoldingFieldSpecByName[args[0]] if !ok { return ops.errorf("%s unknown field: %#v", spec.Name, args[0]) } @@ -1160,7 +1138,7 @@ func assembleAssetHolding(ops *OpStream, spec *OpSpec, args []string) error { val := fs.field ops.pending.WriteByte(spec.Opcode) ops.pending.WriteByte(uint8(val)) - ops.trace("%s (%s)", fs.field.String(), fs.ftype.String()) + ops.trace("%s (%s)", fs.field, fs.ftype) ops.returns(fs.ftype, StackUint64) return nil } @@ -1169,7 +1147,7 @@ func assembleAssetParams(ops *OpStream, spec *OpSpec, args []string) error { if len(args) != 1 { return ops.errorf("%s expects one argument", spec.Name) } - fs, ok := assetParamsFieldSpecByName[args[0]] + fs, ok := AssetParamsFieldSpecByName[args[0]] if !ok { return ops.errorf("%s unknown field: %#v", spec.Name, args[0]) } @@ -1181,7 +1159,7 @@ func assembleAssetParams(ops *OpStream, spec *OpSpec, args []string) error { val := fs.field ops.pending.WriteByte(spec.Opcode) ops.pending.WriteByte(uint8(val)) - ops.trace("%s (%s)", fs.field.String(), fs.ftype.String()) + ops.trace("%s (%s)", fs.field, fs.ftype) ops.returns(fs.ftype, StackUint64) return nil } @@ -1190,7 +1168,28 @@ func assembleAppParams(ops *OpStream, spec *OpSpec, args []string) error { if len(args) != 1 { return ops.errorf("%s expects one argument", spec.Name) } - fs, ok := appParamsFieldSpecByName[args[0]] + fs, ok := AppParamsFieldSpecByName[args[0]] + if !ok { + return ops.errorf("%s unknown field: %#v", spec.Name, args[0]) + } + if fs.version > ops.Version { + //nolint:errcheck // we continue to maintain typestack + ops.errorf("%s %s available in version %d. Missed #pragma version?", spec.Name, args[0], fs.version) + } + + val := fs.field + ops.pending.WriteByte(spec.Opcode) + ops.pending.WriteByte(uint8(val)) + ops.trace("%s (%s)", fs.field, fs.ftype) + ops.returns(fs.ftype, StackUint64) + return nil +} + +func assembleAcctParams(ops *OpStream, spec *OpSpec, args []string) error { + if len(args) != 1 { + return ops.errorf("%s expects one argument", spec.Name) + } + fs, ok := AcctParamsFieldSpecByName[args[0]] if !ok { return ops.errorf("%s unknown field: %#v", spec.Name, args[0]) } @@ -1202,7 +1201,7 @@ func assembleAppParams(ops *OpStream, spec *OpSpec, args []string) error { val := fs.field ops.pending.WriteByte(spec.Opcode) ops.pending.WriteByte(uint8(val)) - ops.trace("%s (%s)", fs.field.String(), fs.ftype.String()) + ops.trace("%s (%s)", fs.field, fs.ftype) ops.returns(fs.ftype, StackUint64) return nil } @@ -1211,13 +1210,15 @@ func asmTxField(ops *OpStream, spec *OpSpec, args []string) error { if len(args) != 1 { return ops.errorf("%s expects one argument", spec.Name) } - fs, ok := txnFieldSpecByName[args[0]] + fs, ok := TxnFieldSpecByName[args[0]] if !ok { - return ops.errorf("txn unknown field: %#v", args[0]) + return ops.errorf("%s unknown field: %#v", spec.Name, args[0]) + } + if fs.itxVersion == 0 { + return ops.errorf("%s %#v is not allowed.", spec.Name, args[0]) } - _, ok = txnaFieldSpecByField[fs.field] - if ok { - return ops.errorf("found array field %#v in %s op", args[0], spec.Name) + if fs.itxVersion > ops.Version { + return ops.errorf("%s %#v available in version %d. Missed #pragma version?", spec.Name, args[0], fs.itxVersion) } ops.pending.WriteByte(spec.Opcode) ops.pending.WriteByte(uint8(fs.field)) @@ -1229,7 +1230,7 @@ func assembleEcdsa(ops *OpStream, spec *OpSpec, args []string) error { return ops.errorf("%s expects one argument", spec.Name) } - cs, ok := ecdsaCurveSpecByName[args[0]] + cs, ok := EcdsaCurveSpecByName[args[0]] if !ok { return ops.errorf("%s unknown field: %#v", spec.Name, args[0]) } @@ -1275,12 +1276,9 @@ func asmDefault(ops *OpStream, spec *OpSpec, args []string) error { } ops.pending.WriteByte(spec.Opcode) for i := 0; i < spec.Details.Size-1; i++ { - val, err := strconv.ParseUint(args[i], 0, 64) + val, err := simpleImm(args[i], "argument") if err != nil { - return ops.error(err) - } - if val > 255 { - return ops.errorf("%s outside 0..255: %d", spec.Name, val) + return ops.errorf("%s %w", spec.Name, err) } ops.pending.WriteByte(byte(val)) } @@ -1434,7 +1432,7 @@ func typeTxField(ops *OpStream, args []string) (StackTypes, StackTypes) { if len(args) != 1 { return oneAny, nil } - fs, ok := txnFieldSpecByName[args[0]] + fs, ok := TxnFieldSpecByName[args[0]] if !ok { return oneAny, nil } @@ -1735,7 +1733,7 @@ func (ops *OpStream) pragma(line string) error { if err != nil { return ops.errorf("bad #pragma version: %#v", value) } - if ver < 1 || ver > AssemblerMaxVersion { + if ver > AssemblerMaxVersion { return ops.errorf("unsupported version: %d", ver) } @@ -2040,7 +2038,7 @@ func (ops *OpStream) optimizeConstants(refs []constReference, constBlock []inter func (ops *OpStream) prependCBlocks() []byte { var scratch [binary.MaxVarintLen64]byte prebytes := bytes.Buffer{} - vlen := binary.PutUvarint(scratch[:], ops.GetVersion()) + vlen := binary.PutUvarint(scratch[:], ops.Version) prebytes.Write(scratch[:vlen]) if len(ops.intc) > 0 && !ops.hasIntcBlock { prebytes.WriteByte(0x20) // intcblock @@ -2239,7 +2237,7 @@ func parseIntcblock(program []byte, pc int) (intc []uint64, nextpc int, err erro pos := pc + 1 numInts, bytesUsed := binary.Uvarint(program[pos:]) if bytesUsed <= 0 { - err = fmt.Errorf("could not decode int const block size at pc=%d", pos) + err = fmt.Errorf("could not decode intcblock size at pc=%d", pos) return } pos += bytesUsed @@ -2268,7 +2266,7 @@ func checkIntConstBlock(cx *EvalContext) error { pos := cx.pc + 1 numInts, bytesUsed := binary.Uvarint(cx.program[pos:]) if bytesUsed <= 0 { - return fmt.Errorf("could not decode int const block size at pc=%d", pos) + return fmt.Errorf("could not decode intcblock size at pc=%d", pos) } pos += bytesUsed if numInts > uint64(len(cx.program)) { @@ -2296,7 +2294,7 @@ func parseBytecBlock(program []byte, pc int) (bytec [][]byte, nextpc int, err er pos := pc + 1 numItems, bytesUsed := binary.Uvarint(program[pos:]) if bytesUsed <= 0 { - err = fmt.Errorf("could not decode []byte const block size at pc=%d", pos) + err = fmt.Errorf("could not decode bytecblock size at pc=%d", pos) return } pos += bytesUsed @@ -2336,7 +2334,7 @@ func checkByteConstBlock(cx *EvalContext) error { pos := cx.pc + 1 numItems, bytesUsed := binary.Uvarint(cx.program[pos:]) if bytesUsed <= 0 { - return fmt.Errorf("could not decode []byte const block size at pc=%d", pos) + return fmt.Errorf("could not decode bytecblock size at pc=%d", pos) } pos += bytesUsed if numItems > uint64(len(cx.program)) { @@ -2546,7 +2544,7 @@ func disTxna(dis *disassembleState, spec *OpSpec) (string, error) { return fmt.Sprintf("%s %s %d", spec.Name, TxnFieldNames[txarg], arrayFieldIdx), nil } -// This is also used to disassemble gtxnas +// disGtxn is also used to disassemble gtxnas, gitxn func disGtxn(dis *disassembleState, spec *OpSpec) (string, error) { lastIdx := dis.pc + 2 if len(dis.program) <= lastIdx { @@ -2562,6 +2560,7 @@ func disGtxn(dis *disassembleState, spec *OpSpec) (string, error) { return fmt.Sprintf("%s %d %s", spec.Name, gi, TxnFieldNames[txarg]), nil } +// disGtxna is also used to disassemble gitxna func disGtxna(dis *disassembleState, spec *OpSpec) (string, error) { lastIdx := dis.pc + 3 if len(dis.program) <= lastIdx { @@ -2575,7 +2574,7 @@ func disGtxna(dis *disassembleState, spec *OpSpec) (string, error) { return "", fmt.Errorf("invalid txn arg index %d at pc=%d", txarg, dis.pc) } arrayFieldIdx := dis.program[dis.pc+3] - return fmt.Sprintf("gtxna %d %s %d", gi, TxnFieldNames[txarg], arrayFieldIdx), nil + return fmt.Sprintf("%s %d %s %d", spec.Name, gi, TxnFieldNames[txarg], arrayFieldIdx), nil } func disGlobal(dis *disassembleState, spec *OpSpec) (string, error) { @@ -2662,6 +2661,20 @@ func disAppParams(dis *disassembleState, spec *OpSpec) (string, error) { return fmt.Sprintf("%s %s", spec.Name, AppParamsFieldNames[arg]), nil } +func disAcctParams(dis *disassembleState, spec *OpSpec) (string, error) { + lastIdx := dis.pc + 1 + if len(dis.program) <= lastIdx { + missing := lastIdx - len(dis.program) + 1 + return "", fmt.Errorf("unexpected %s opcode end: missing %d bytes", spec.Name, missing) + } + dis.nextpc = dis.pc + 2 + arg := dis.program[dis.pc+1] + if int(arg) >= len(AcctParamsFieldNames) { + return "", fmt.Errorf("invalid acct params arg index %d at pc=%d", arg, dis.pc) + } + return fmt.Sprintf("%s %s", spec.Name, AcctParamsFieldNames[arg]), nil +} + func disTxField(dis *disassembleState, spec *OpSpec) (string, error) { lastIdx := dis.pc + 1 if len(dis.program) <= lastIdx { |