Skip to content

Commit beea6dd

Browse files
committed
Impose limits on reading and writing of box bytes
1 parent e7b20e9 commit beea6dd

File tree

19 files changed

+528
-491
lines changed

19 files changed

+528
-491
lines changed

cmd/goal/application.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -359,7 +359,7 @@ func translateBoxRefs(input []boxRef, foreignApps []uint64) []transactions.BoxRe
359359
}
360360
output[i] = transactions.BoxRef{
361361
Index: index,
362-
Name: string(rawName),
362+
Name: rawName,
363363
}
364364
}
365365
return output

config/consensus.go

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -342,7 +342,14 @@ type ConsensusParams struct {
342342
BoxByteMinBalance uint64
343343

344344
// Number of box references allowed
345-
MaxAppBoxReferences uint64
345+
MaxAppBoxReferences int
346+
347+
// Amount added to a txgroup's box I/O budget per box ref supplied.
348+
// For reads: the sum of the sizes of all boxes in the group must be less than I/O budget
349+
// For writes: the sum of the sizes of all boxes created or written must be less than I/O budget
350+
// In both cases, what matters is the sizes of the boxes touched, not the
351+
// number of times they are touched, or the size of the touches.
352+
BytesPerBoxReference uint64
346353

347354
// maximum number of total key/value pairs allowed by a given
348355
// LocalStateSchema (and therefore allowed in LocalState)
@@ -1163,10 +1170,11 @@ func initConsensusProtocols() {
11631170
vFuture.EnableSHA256TxnCommitmentHeader = true
11641171

11651172
// Boxes (unlimited global storage)
1166-
vFuture.MaxBoxSize = 8096
1167-
vFuture.BoxFlatMinBalance = 2500
1168-
vFuture.BoxByteMinBalance = 400
1173+
vFuture.MaxBoxSize = 4 * 8096
1174+
vFuture.BoxFlatMinBalance = 10000
1175+
vFuture.BoxByteMinBalance = 350
11691176
vFuture.MaxAppBoxReferences = 8
1177+
vFuture.BytesPerBoxReference = 8096
11701178

11711179
Consensus[protocol.ConsensusFuture] = vFuture
11721180
}

data/transactions/application.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ type ApplicationCallTxnFields struct {
122122
ForeignApps []basics.AppIndex `codec:"apfa,allocbound=encodedMaxForeignApps"`
123123

124124
// Boxes are the boxes that can be accessed by this transaction (and others
125-
// in the same group). The Index in the boxRef is the slot of ForeignApps
125+
// in the same group). The Index in the BoxRef is the slot of ForeignApps
126126
// that the name is asscoiated with (shifted by 1, so 0 indicates "current
127127
// app")
128128
Boxes []BoxRef `codec:"apbx,allocbound=encodedMaxBoxes"`
@@ -172,7 +172,7 @@ type BoxRef struct {
172172
_struct struct{} `codec:",omitempty,omitemptyarray"`
173173

174174
Index uint64 `codec:"i"`
175-
Name string `codec:"n"`
175+
Name []byte `codec:"n"`
176176
}
177177

178178
// Empty indicates whether or not all the fields in the

data/transactions/json.go

Lines changed: 0 additions & 60 deletions
This file was deleted.

data/transactions/json_test.go

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,12 @@
1616

1717
package transactions_test
1818

19+
/* These tests are pretty low-value now. They test something very basic about
20+
our codec for encoding []byte as base64 strings in json. The test were
21+
written we BoxRef contained a string instead of []byte. When that was true,
22+
these tests were more important because there was work that had to be done to
23+
make it happen (implement MarshalJSON and UnmarshalJSON) */
24+
1925
import (
2026
"strings"
2127
"testing"
@@ -41,16 +47,16 @@ func compact(data []byte) string {
4147

4248
// TestJsonMarshal ensures that BoxRef names are b64 encoded, since they may not be characters.
4349
func TestJsonMarshal(t *testing.T) {
44-
marshal := protocol.EncodeJSON(transactions.BoxRef{Index: 4, Name: "joe"})
50+
marshal := protocol.EncodeJSON(transactions.BoxRef{Index: 4, Name: []byte("joe")})
4551
require.Equal(t, `{"i":4,"n":"am9l"}`, compact(marshal))
4652

47-
marshal = protocol.EncodeJSON(transactions.BoxRef{Index: 0, Name: "joe"})
53+
marshal = protocol.EncodeJSON(transactions.BoxRef{Index: 0, Name: []byte("joe")})
4854
require.Equal(t, `{"n":"am9l"}`, compact(marshal))
4955

50-
marshal = protocol.EncodeJSON(transactions.BoxRef{Index: 1, Name: ""})
56+
marshal = protocol.EncodeJSON(transactions.BoxRef{Index: 1, Name: []byte("")})
5157
require.Equal(t, `{"i":1}`, compact(marshal))
5258

53-
marshal = protocol.EncodeJSON(transactions.BoxRef{Index: 0, Name: ""})
59+
marshal = protocol.EncodeJSON(transactions.BoxRef{Index: 0, Name: []byte("")})
5460
require.Equal(t, `{}`, compact(marshal))
5561
}
5662

@@ -59,16 +65,19 @@ func TestJsonUnmarshal(t *testing.T) {
5965
var br transactions.BoxRef
6066

6167
decode(`{"i":4,"n":"am9l"}`, &br)
62-
require.Equal(t, transactions.BoxRef{Index: 4, Name: "joe"}, br)
68+
require.Equal(t, transactions.BoxRef{Index: 4, Name: []byte("joe")}, br)
6369

70+
br = transactions.BoxRef{}
6471
decode(`{"n":"am9l"}`, &br)
65-
require.Equal(t, transactions.BoxRef{Index: 0, Name: "joe"}, br)
72+
require.Equal(t, transactions.BoxRef{Index: 0, Name: []byte("joe")}, br)
6673

74+
br = transactions.BoxRef{}
6775
decode(`{"i":4}`, &br)
68-
require.Equal(t, transactions.BoxRef{Index: 4, Name: ""}, br)
76+
require.Equal(t, transactions.BoxRef{Index: 4, Name: nil}, br)
6977

78+
br = transactions.BoxRef{}
7079
decode(`{}`, &br)
71-
require.Equal(t, transactions.BoxRef{Index: 0, Name: ""}, br)
80+
require.Equal(t, transactions.BoxRef{Index: 0, Name: nil}, br)
7281
}
7382

7483
// TestTxnJson tests a few more things about how our Transactions get JSON
@@ -82,7 +91,7 @@ func TestTxnJson(t *testing.T) {
8291
require.Contains(t, compact(marshal), `"snd":"AEBA`)
8392

8493
txn = txntest.Txn{
85-
Boxes: []transactions.BoxRef{{Index: 3, Name: "john"}},
94+
Boxes: []transactions.BoxRef{{Index: 3, Name: []byte("john")}},
8695
}
8796
marshal = protocol.EncodeJSON(txn.Txn())
8897
require.Contains(t, compact(marshal), `"apbx":[{"i":3,"n":"am9obg=="}]`)

data/transactions/logic/assembler.go

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -452,7 +452,7 @@ func (ops *OpStream) ByteLiteral(val []byte) {
452452

453453
func asmInt(ops *OpStream, spec *OpSpec, args []string) error {
454454
if len(args) != 1 {
455-
return ops.error("int needs one argument")
455+
return ops.errorf("%s needs one immediate argument, was given %d", spec.Name, len(args))
456456
}
457457
// check txn type constants
458458
i, ok := txnTypeMap[args[0]]
@@ -477,7 +477,7 @@ func asmInt(ops *OpStream, spec *OpSpec, args []string) error {
477477
// Explicit invocation of const lookup and push
478478
func asmIntC(ops *OpStream, spec *OpSpec, args []string) error {
479479
if len(args) != 1 {
480-
return ops.error("intc operation needs one argument")
480+
return ops.errorf("%s needs one immediate argument, was given %d", spec.Name, len(args))
481481
}
482482
constIndex, err := simpleImm(args[0], "constant")
483483
if err != nil {
@@ -488,7 +488,7 @@ func asmIntC(ops *OpStream, spec *OpSpec, args []string) error {
488488
}
489489
func asmByteC(ops *OpStream, spec *OpSpec, args []string) error {
490490
if len(args) != 1 {
491-
return ops.error("bytec operation needs one argument")
491+
return ops.errorf("%s needs one immediate argument, was given %d", spec.Name, len(args))
492492
}
493493
constIndex, err := simpleImm(args[0], "constant")
494494
if err != nil {
@@ -500,7 +500,7 @@ func asmByteC(ops *OpStream, spec *OpSpec, args []string) error {
500500

501501
func asmPushInt(ops *OpStream, spec *OpSpec, args []string) error {
502502
if len(args) != 1 {
503-
return ops.errorf("%s needs one argument", spec.Name)
503+
return ops.errorf("%s needs one immediate argument, was given %d", spec.Name, len(args))
504504
}
505505
val, err := strconv.ParseUint(args[0], 0, 64)
506506
if err != nil {
@@ -514,14 +514,14 @@ func asmPushInt(ops *OpStream, spec *OpSpec, args []string) error {
514514
}
515515
func asmPushBytes(ops *OpStream, spec *OpSpec, args []string) error {
516516
if len(args) == 0 {
517-
return ops.errorf("%s operation needs byte literal argument", spec.Name)
517+
return ops.errorf("%s needs byte literal argument", spec.Name)
518518
}
519519
val, consumed, err := parseBinaryArgs(args)
520520
if err != nil {
521521
return ops.error(err)
522522
}
523523
if len(args) != consumed {
524-
return ops.errorf("%s operation with extraneous argument", spec.Name)
524+
return ops.errorf("%s with extraneous argument", spec.Name)
525525
}
526526
ops.pending.WriteByte(spec.Opcode)
527527
var scratch [binary.MaxVarintLen64]byte
@@ -680,14 +680,14 @@ func parseStringLiteral(input string) (result []byte, err error) {
680680
// byte "this is a string\n"
681681
func asmByte(ops *OpStream, spec *OpSpec, args []string) error {
682682
if len(args) == 0 {
683-
return ops.errorf("%s operation needs byte literal argument", spec.Name)
683+
return ops.errorf("%s needs byte literal argument", spec.Name)
684684
}
685685
val, consumed, err := parseBinaryArgs(args)
686686
if err != nil {
687687
return ops.error(err)
688688
}
689689
if len(args) != consumed {
690-
return ops.errorf("%s operation with extraneous argument", spec.Name)
690+
return ops.errorf("%s with extraneous argument", spec.Name)
691691
}
692692
ops.ByteLiteral(val)
693693
return nil
@@ -773,7 +773,7 @@ func asmByteCBlock(ops *OpStream, spec *OpSpec, args []string) error {
773773
// parses base32-with-checksum account address strings into a byte literal
774774
func asmAddr(ops *OpStream, spec *OpSpec, args []string) error {
775775
if len(args) != 1 {
776-
return ops.error("addr operation needs one argument")
776+
return ops.errorf("%s needs one immediate argument, was given %d", spec.Name, len(args))
777777
}
778778
addr, err := basics.UnmarshalChecksumAddress(args[0])
779779
if err != nil {
@@ -785,7 +785,7 @@ func asmAddr(ops *OpStream, spec *OpSpec, args []string) error {
785785

786786
func asmArg(ops *OpStream, spec *OpSpec, args []string) error {
787787
if len(args) != 1 {
788-
return ops.error("arg operation needs one argument")
788+
return ops.errorf("%s needs one immediate argument, was given %d", spec.Name, len(args))
789789
}
790790
val, err := simpleImm(args[0], "argument")
791791
if err != nil {
@@ -810,7 +810,7 @@ func asmArg(ops *OpStream, spec *OpSpec, args []string) error {
810810

811811
func asmBranch(ops *OpStream, spec *OpSpec, args []string) error {
812812
if len(args) != 1 {
813-
return ops.error("branch operation needs label argument")
813+
return ops.errorf("%s needs a single label argument", spec.Name)
814814
}
815815

816816
ops.referToLabel(ops.pending.Len(), args[0])

data/transactions/logic/assembler_test.go

Lines changed: 32 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -763,8 +763,8 @@ func TestAssembleBytes(t *testing.T) {
763763
expectedOptimizedConsts := "018006616263646566"
764764

765765
bad := [][]string{
766-
{"byte", "...operation needs byte literal argument"},
767-
{`byte "john" "doe"`, "...operation with extraneous argument"},
766+
{"byte", "...needs byte literal argument"},
767+
{`byte "john" "doe"`, "...with extraneous argument"},
768768
}
769769

770770
for v := uint64(1); v <= AssemblerMaxVersion; v++ {
@@ -1543,17 +1543,40 @@ func TestConstantArgs(t *testing.T) {
15431543
t.Parallel()
15441544

15451545
for v := uint64(1); v <= AssemblerMaxVersion; v++ {
1546-
testProg(t, "int", v, Expect{1, "int needs one argument"})
1547-
testProg(t, "intc", v, Expect{1, "intc operation needs one argument"})
1548-
testProg(t, "byte", v, Expect{1, "byte operation needs byte literal argument"})
1549-
testProg(t, "bytec", v, Expect{1, "bytec operation needs one argument"})
1550-
testProg(t, "addr", v, Expect{1, "addr operation needs one argument"})
1546+
testProg(t, "int", v, Expect{1, "int needs one immediate argument, was given 0"})
1547+
testProg(t, "int 1 2", v, Expect{1, "int needs one immediate argument, was given 2"})
1548+
testProg(t, "intc", v, Expect{1, "intc needs one immediate argument, was given 0"})
1549+
testProg(t, "intc hi bye", v, Expect{1, "intc needs one immediate argument, was given 2"})
1550+
testProg(t, "byte", v, Expect{1, "byte needs byte literal argument"})
1551+
testProg(t, "bytec", v, Expect{1, "bytec needs one immediate argument, was given 0"})
1552+
testProg(t, "bytec 1 x", v, Expect{1, "bytec needs one immediate argument, was given 2"})
1553+
testProg(t, "addr", v, Expect{1, "addr needs one immediate argument, was given 0"})
1554+
testProg(t, "addr x y", v, Expect{1, "addr needs one immediate argument, was given 2"})
15511555
}
15521556
for v := uint64(3); v <= AssemblerMaxVersion; v++ {
1553-
testProg(t, "pushint", v, Expect{1, "pushint needs one argument"})
1554-
testProg(t, "pushbytes", v, Expect{1, "pushbytes operation needs byte literal argument"})
1557+
testProg(t, "pushint", v, Expect{1, "pushint needs one immediate argument, was given 0"})
1558+
testProg(t, "pushint 3 4", v, Expect{1, "pushint needs one immediate argument, was given 2"})
1559+
testProg(t, "pushbytes", v, Expect{1, "pushbytes needs byte literal argument"})
15551560
}
1561+
}
1562+
1563+
func TestBranchArgs(t *testing.T) {
1564+
partitiontest.PartitionTest(t)
1565+
t.Parallel()
15561566

1567+
for v := uint64(2); v <= AssemblerMaxVersion; v++ {
1568+
testProg(t, "b", v, Expect{1, "b needs a single label argument"})
1569+
testProg(t, "b lab1 lab2", v, Expect{1, "b needs a single label argument"})
1570+
testProg(t, "int 1; bz", v, Expect{2, "bz needs a single label argument"})
1571+
testProg(t, "int 1; bz a b", v, Expect{2, "bz needs a single label argument"})
1572+
testProg(t, "int 1; bnz", v, Expect{2, "bnz needs a single label argument"})
1573+
testProg(t, "int 1; bnz c d", v, Expect{2, "bnz needs a single label argument"})
1574+
}
1575+
1576+
for v := uint64(4); v <= AssemblerMaxVersion; v++ {
1577+
testProg(t, "callsub", v, Expect{1, "callsub needs a single label argument"})
1578+
testProg(t, "callsub one two", v, Expect{1, "callsub needs a single label argument"})
1579+
}
15571580
}
15581581

15591582
func TestAssembleDisassembleErrors(t *testing.T) {

0 commit comments

Comments
 (0)