Fix TX payload for DO testnets (#9540) (#9543)

* Added print

* Fix unmarshall

* Fix unmarshalling

* Simplified steps to unmarshall

* minor

* Use 'encoding/hex'

* Forget about C, this is Go!

* gosec warning

* Set maximum payload size

* nosec annotation

(cherry picked from commit b42c439776)

Co-authored-by: Sergio Mena <sergio@informal.systems>
This commit is contained in:
mergify[bot]
2022-10-12 20:21:56 +02:00
committed by GitHub
parent df5fe1fb21
commit 3ec6e424d6

View File

@@ -3,7 +3,7 @@ package payload
import ( import (
"bytes" "bytes"
"crypto/rand" "crypto/rand"
"errors" "encoding/hex"
"fmt" "fmt"
"math" "math"
@@ -12,6 +12,7 @@ import (
) )
const keyPrefix = "a=" const keyPrefix = "a="
const maxPayloadSize = 4 * 1024 * 1024
// NewBytes generates a new payload and returns the encoded representation of // NewBytes generates a new payload and returns the encoded representation of
// the payload as a slice of bytes. NewBytes uses the fields on the Options // the payload as a slice of bytes. NewBytes uses the fields on the Options
@@ -25,10 +26,16 @@ func NewBytes(p *Payload) ([]byte, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
if p.Size < uint64(us) { if p.Size > maxPayloadSize {
return nil, fmt.Errorf("configured size %d not large enough to fit unpadded transaction of size %d", p.Size, us) return nil, fmt.Errorf("configured size %d is too large (>%d)", p.Size, maxPayloadSize)
} }
p.Padding = make([]byte, p.Size-uint64(us)) pSize := int(p.Size) // #nosec -- The "if" above makes this cast safe
if pSize < us {
return nil, fmt.Errorf("configured size %d not large enough to fit unpadded transaction of size %d", pSize, us)
}
// We halve the padding size because we transform the TX to hex
p.Padding = make([]byte, (pSize-us)/2)
_, err = rand.Read(p.Padding) _, err = rand.Read(p.Padding)
if err != nil { if err != nil {
return nil, err return nil, err
@@ -37,22 +44,28 @@ func NewBytes(p *Payload) ([]byte, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
h := []byte(hex.EncodeToString(b))
// prepend a single key so that the kv store only ever stores a single // prepend a single key so that the kv store only ever stores a single
// transaction instead of storing all tx and ballooning in size. // transaction instead of storing all tx and ballooning in size.
return append([]byte(keyPrefix), b...), nil return append([]byte(keyPrefix), h...), nil
} }
// FromBytes extracts a paylod from the byte representation of the payload. // FromBytes extracts a paylod from the byte representation of the payload.
// FromBytes leaves the padding untouched, returning it to the caller to handle // FromBytes leaves the padding untouched, returning it to the caller to handle
// or discard per their preference. // or discard per their preference.
func FromBytes(b []byte) (*Payload, error) { func FromBytes(b []byte) (*Payload, error) {
p := &Payload{} trH := bytes.TrimPrefix(b, []byte(keyPrefix))
tr := bytes.TrimPrefix(b, []byte(keyPrefix)) if bytes.Equal(b, trH) {
if bytes.Equal(b, tr) { return nil, fmt.Errorf("payload bytes missing key prefix '%s'", keyPrefix)
return nil, errors.New("payload bytes missing key prefix")
} }
err := proto.Unmarshal(tr, p) trB, err := hex.DecodeString(string(trH))
if err != nil {
return nil, err
}
p := &Payload{}
err = proto.Unmarshal(trB, p)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -83,5 +96,6 @@ func CalculateUnpaddedSize(p *Payload) (int, error) {
if err != nil { if err != nil {
return 0, err return 0, err
} }
return len(b) + len(keyPrefix), nil h := []byte(hex.EncodeToString(b))
return len(h) + len(keyPrefix), nil
} }