github.com/nspcc-dev/neo-go@v0.105.2-0.20240517133400-6be757af3eba/pkg/network/payload/extensible.go (about)

     1  package payload
     2  
     3  import (
     4  	"errors"
     5  
     6  	"github.com/nspcc-dev/neo-go/pkg/core/transaction"
     7  	"github.com/nspcc-dev/neo-go/pkg/crypto/hash"
     8  	"github.com/nspcc-dev/neo-go/pkg/io"
     9  	"github.com/nspcc-dev/neo-go/pkg/util"
    10  )
    11  
    12  const maxExtensibleCategorySize = 32
    13  
    14  // ConsensusCategory is a message category for consensus-related extensible
    15  // payloads.
    16  const ConsensusCategory = "dBFT"
    17  
    18  // Extensible represents a payload containing arbitrary data.
    19  type Extensible struct {
    20  	// Category is the payload type.
    21  	Category string
    22  	// ValidBlockStart is the starting height for a payload to be valid.
    23  	ValidBlockStart uint32
    24  	// ValidBlockEnd is the height after which a payload becomes invalid.
    25  	ValidBlockEnd uint32
    26  	// Sender is the payload sender or signer.
    27  	Sender util.Uint160
    28  	// Data is custom payload data.
    29  	Data []byte
    30  	// Witness is payload witness.
    31  	Witness transaction.Witness
    32  
    33  	hash util.Uint256
    34  }
    35  
    36  var errInvalidPadding = errors.New("invalid padding")
    37  
    38  // NewExtensible creates a new extensible payload.
    39  func NewExtensible() *Extensible {
    40  	return &Extensible{}
    41  }
    42  
    43  func (e *Extensible) encodeBinaryUnsigned(w *io.BinWriter) {
    44  	w.WriteString(e.Category)
    45  	w.WriteU32LE(e.ValidBlockStart)
    46  	w.WriteU32LE(e.ValidBlockEnd)
    47  	w.WriteBytes(e.Sender[:])
    48  	w.WriteVarBytes(e.Data)
    49  }
    50  
    51  // EncodeBinary implements io.Serializable.
    52  func (e *Extensible) EncodeBinary(w *io.BinWriter) {
    53  	e.encodeBinaryUnsigned(w)
    54  	w.WriteB(1)
    55  	e.Witness.EncodeBinary(w)
    56  }
    57  
    58  func (e *Extensible) decodeBinaryUnsigned(r *io.BinReader) {
    59  	e.Category = r.ReadString(maxExtensibleCategorySize)
    60  	e.ValidBlockStart = r.ReadU32LE()
    61  	e.ValidBlockEnd = r.ReadU32LE()
    62  	r.ReadBytes(e.Sender[:])
    63  	e.Data = r.ReadVarBytes(MaxSize)
    64  }
    65  
    66  // DecodeBinary implements io.Serializable.
    67  func (e *Extensible) DecodeBinary(r *io.BinReader) {
    68  	e.decodeBinaryUnsigned(r)
    69  	if r.ReadB() != 1 {
    70  		if r.Err != nil {
    71  			return
    72  		}
    73  		r.Err = errInvalidPadding
    74  		return
    75  	}
    76  	e.Witness.DecodeBinary(r)
    77  }
    78  
    79  // Hash returns payload hash.
    80  func (e *Extensible) Hash() util.Uint256 {
    81  	if e.hash.Equals(util.Uint256{}) {
    82  		e.createHash()
    83  	}
    84  	return e.hash
    85  }
    86  
    87  // createHash creates hashes of the payload.
    88  func (e *Extensible) createHash() {
    89  	buf := io.NewBufBinWriter()
    90  	e.encodeBinaryUnsigned(buf.BinWriter)
    91  	e.hash = hash.Sha256(buf.Bytes())
    92  }