Skip to content

Commit

Permalink
scale: allocate slice elements when decoding (#587)
Browse files Browse the repository at this point in the history
* update DecodeArray to allocate a slice instead of assigning to the interface that's passed in, allows for arrays to be decoded without knowing how many elements are in it
* update DecodeTuple to handle [][]byte
  • Loading branch information
noot authored and ryanchristo committed Jun 24, 2020
1 parent becfa9d commit b1ba9a9
Show file tree
Hide file tree
Showing 7 changed files with 71 additions and 25 deletions.
27 changes: 20 additions & 7 deletions codec/decode.go
Original file line number Diff line number Diff line change
Expand Up @@ -325,10 +325,6 @@ func (sd *Decoder) DecodeArray(t interface{}) (interface{}, error) {
v = reflect.ValueOf(t)
}

if v.Len() == 0 {
return t, nil
}

var err error
var o interface{}

Expand All @@ -341,10 +337,12 @@ func (sd *Decoder) DecodeArray(t interface{}) (interface{}, error) {
return t, nil
}

sl := reflect.MakeSlice(v.Type(), int(length), int(length))

for i := 0; i < int(length); i++ {
arrayValue := v.Index(i)
arrayValue := sl.Index(i)

switch v.Index(i).Interface().(type) {
switch sl.Index(i).Interface().(type) {
case []byte:
o, err = sd.DecodeByteArray()
if err != nil {
Expand All @@ -371,7 +369,14 @@ func (sd *Decoder) DecodeArray(t interface{}) (interface{}, error) {
}
}

return t, err
switch t.(type) {
case [][]byte:
copy(t.([][]byte), sl.Interface().([][]byte))
case [][32]byte:
copy(t.([][32]byte), sl.Interface().([][32]byte))
}

return sl.Interface(), err
}

// DecodeTuple accepts a byte array representing the SCALE encoded tuple and an interface. This interface should be a pointer
Expand Down Expand Up @@ -415,6 +420,14 @@ func (sd *Decoder) DecodeTuple(t interface{}) (interface{}, error) {
// get the pointer to the value and set the value
ptr := fieldValue.(*[]byte)
*ptr = o.([]byte)
case [][]byte:
o, err = sd.DecodeArray([][]byte{})
if err != nil {
break
}

ptr := fieldValue.(*[][]byte)
*ptr = o.([][]byte)
case int8:
o, err = sd.DecodeFixedWidthInt(int8(0))
if err != nil {
Expand Down
11 changes: 6 additions & 5 deletions codec/decode_ptr.go
Original file line number Diff line number Diff line change
Expand Up @@ -193,20 +193,21 @@ func (sd *Decoder) DecodePtrBool(output interface{}) error {

// DecodePtrIntArray decodes a byte array to an array of ints
func (sd *Decoder) DecodePtrIntArray(t interface{}) error {
_, err := sd.DecodeInteger()
length, err := sd.DecodeInteger()
if err != nil {
return err
}

for i := range t.([]int) {
//var temp int64
//var err error
sl := make([]int, length)
for i := range sl {
temp, err := sd.DecodeInteger()
t.([]int)[i] = int(temp)
sl[i] = int(temp)
if err != nil {
break
}
}

copy(t.([]int), sl)
return nil
}

Expand Down
33 changes: 32 additions & 1 deletion codec/decode_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -317,7 +317,6 @@ var decodeTupleTests = []decodeTupleTest{
}

var decodeArrayTests = []decodeArrayTest{
{val: []byte{}, t: [][]byte{}, output: [][]byte{}},
{val: []byte{0x00}, t: []int{}, output: []int{}},
{val: []byte{0x04, 0x04}, t: make([]int, 1), output: []int{1}},
{val: []byte{0x10, 0x04, 0x08, 0x0c, 0x10}, t: make([]int, 4), output: []int{1, 2, 3, 4}},
Expand Down Expand Up @@ -508,3 +507,35 @@ func TestDecodeArrays(t *testing.T) {
}
}
}

func TestDecodeEmptyArray(t *testing.T) {
expected := &struct {
Number *big.Int
Digest [][]byte
}{
big.NewInt(9),
[][]byte{{0xa, 0xb, 0xc, 0xd}, {0xe, 0xf}},
}

testStruct := &struct {
Number *big.Int
Digest [][]byte
}{
big.NewInt(0),
[][]byte{},
}

enc, err := Encode(expected)
if err != nil {
t.Fatal(err)
}

output, err := Decode(enc, testStruct)
if err != nil {
t.Fatal(err)
}

if !reflect.DeepEqual(output, expected) {
t.Fatalf("Fail: got %v expected %v", output, expected)
}
}
8 changes: 4 additions & 4 deletions consensus/babe/babe.go
Original file line number Diff line number Diff line change
Expand Up @@ -294,7 +294,7 @@ func (b *Session) buildBlock(parent *types.Header, slot Slot) (*types.Block, err
// initialize block header
encodedHeader, err := scale.Encode(header)
if err != nil {
return nil, err
return nil, fmt.Errorf("cannot encode header: %s", err)
}
err = b.initializeBlock(encodedHeader)
if err != nil {
Expand All @@ -304,21 +304,21 @@ func (b *Session) buildBlock(parent *types.Header, slot Slot) (*types.Block, err
// add block inherents
err = b.buildBlockInherents(slot)
if err != nil {
return nil, err
return nil, fmt.Errorf("cannot build inherents: %s", err)
}

// add block extrinsics
included, err := b.buildBlockExtrinsics(slot)
if err != nil {
return nil, err
return nil, fmt.Errorf("cannot build extrisnics: %s", err)
}

// finalize block
log.Trace("build_block finalize block")
block, err := b.finalizeBlock()
if err != nil {
b.addToQueue(included)
return nil, err
return nil, fmt.Errorf("cannot finalize block: %s", err)
}

block.Header.ParentHash = parent.Hash()
Expand Down
13 changes: 7 additions & 6 deletions consensus/babe/runtime.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,11 +64,12 @@ func (b *Session) finalizeBlock() (*types.Block, error) {
return nil, err
}

bh := &types.Block{
Header: new(types.Header),
Body: new(types.Body),
}

// TODO: finalize block actually returns a header, not a block. need to update this function
// as well as buildBlock
bh := new(types.Header)
_, err = scale.Decode(data, bh)
return bh, err
return &types.Block{
Header: bh,
Body: nil,
}, err
}
2 changes: 1 addition & 1 deletion core/service_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ func TestValidateTransaction(t *testing.T) {
// https://github.com/paritytech/substrate/blob/ea2644a235f4b189c8029b9c9eac9d4df64ee91e/core/test-runtime/src/system.rs#L190
expected := &transaction.Validity{
Priority: 69,
Requires: [][]byte{{}},
Requires: [][]byte{},
// https://github.com/paritytech/substrate/blob/ea2644a235f4b189c8029b9c9eac9d4df64ee91e/core/test-runtime/src/system.rs#L173
Provides: [][]byte{{146, 157, 61, 99, 63, 98, 30, 242, 128, 49, 150, 90, 140, 165, 187, 249}},
Longevity: 64,
Expand Down
2 changes: 1 addition & 1 deletion p2p/message_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -499,7 +499,7 @@ func TestDecodeBlockAnnounceMessage(t *testing.T) {
Number: big.NewInt(1),
StateRoot: stateRoot,
ExtrinsicsRoot: extrinsicsRoot,
Digest: nil,
Digest: [][]byte{},
}

if !reflect.DeepEqual(bhm, expected) {
Expand Down

0 comments on commit b1ba9a9

Please sign in to comment.