2021-01-13 15:12:40 +00:00
|
|
|
package payload
|
|
|
|
|
|
|
|
import (
|
|
|
|
"errors"
|
|
|
|
|
|
|
|
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
|
|
|
|
"github.com/nspcc-dev/neo-go/pkg/crypto/hash"
|
|
|
|
"github.com/nspcc-dev/neo-go/pkg/io"
|
|
|
|
"github.com/nspcc-dev/neo-go/pkg/util"
|
|
|
|
)
|
|
|
|
|
2021-05-12 15:13:14 +00:00
|
|
|
const maxExtensibleCategorySize = 32
|
2021-01-13 15:12:40 +00:00
|
|
|
|
2022-07-28 15:30:14 +00:00
|
|
|
// ConsensusCategory is a message category for consensus-related extensible
|
|
|
|
// payloads.
|
|
|
|
const ConsensusCategory = "dBFT"
|
|
|
|
|
2022-04-20 18:30:09 +00:00
|
|
|
// Extensible represents a payload containing arbitrary data.
|
2021-01-13 15:12:40 +00:00
|
|
|
type Extensible struct {
|
2022-04-20 18:30:09 +00:00
|
|
|
// Category is the payload type.
|
2021-01-13 15:12:40 +00:00
|
|
|
Category string
|
2022-04-20 18:30:09 +00:00
|
|
|
// ValidBlockStart is the starting height for a payload to be valid.
|
2021-01-13 15:12:40 +00:00
|
|
|
ValidBlockStart uint32
|
2022-04-20 18:30:09 +00:00
|
|
|
// ValidBlockEnd is the height after which a payload becomes invalid.
|
2021-01-13 15:12:40 +00:00
|
|
|
ValidBlockEnd uint32
|
2022-04-20 18:30:09 +00:00
|
|
|
// Sender is the payload sender or signer.
|
2021-01-13 15:12:40 +00:00
|
|
|
Sender util.Uint160
|
|
|
|
// Data is custom payload data.
|
|
|
|
Data []byte
|
|
|
|
// Witness is payload witness.
|
|
|
|
Witness transaction.Witness
|
|
|
|
|
2021-03-25 18:59:54 +00:00
|
|
|
hash util.Uint256
|
2021-01-13 15:12:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
var errInvalidPadding = errors.New("invalid padding")
|
|
|
|
|
2022-04-20 18:30:09 +00:00
|
|
|
// NewExtensible creates a new extensible payload.
|
2021-03-25 18:59:54 +00:00
|
|
|
func NewExtensible() *Extensible {
|
|
|
|
return &Extensible{}
|
2021-01-13 15:12:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (e *Extensible) encodeBinaryUnsigned(w *io.BinWriter) {
|
|
|
|
w.WriteString(e.Category)
|
|
|
|
w.WriteU32LE(e.ValidBlockStart)
|
|
|
|
w.WriteU32LE(e.ValidBlockEnd)
|
|
|
|
w.WriteBytes(e.Sender[:])
|
|
|
|
w.WriteVarBytes(e.Data)
|
|
|
|
}
|
|
|
|
|
|
|
|
// EncodeBinary implements io.Serializable.
|
|
|
|
func (e *Extensible) EncodeBinary(w *io.BinWriter) {
|
|
|
|
e.encodeBinaryUnsigned(w)
|
|
|
|
w.WriteB(1)
|
|
|
|
e.Witness.EncodeBinary(w)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (e *Extensible) decodeBinaryUnsigned(r *io.BinReader) {
|
|
|
|
e.Category = r.ReadString(maxExtensibleCategorySize)
|
|
|
|
e.ValidBlockStart = r.ReadU32LE()
|
|
|
|
e.ValidBlockEnd = r.ReadU32LE()
|
|
|
|
r.ReadBytes(e.Sender[:])
|
2021-02-15 12:19:05 +00:00
|
|
|
e.Data = r.ReadVarBytes(MaxSize)
|
2021-01-13 15:12:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// DecodeBinary implements io.Serializable.
|
|
|
|
func (e *Extensible) DecodeBinary(r *io.BinReader) {
|
|
|
|
e.decodeBinaryUnsigned(r)
|
|
|
|
if r.ReadB() != 1 {
|
|
|
|
if r.Err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
r.Err = errInvalidPadding
|
|
|
|
return
|
|
|
|
}
|
|
|
|
e.Witness.DecodeBinary(r)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Hash returns payload hash.
|
|
|
|
func (e *Extensible) Hash() util.Uint256 {
|
|
|
|
if e.hash.Equals(util.Uint256{}) {
|
|
|
|
e.createHash()
|
|
|
|
}
|
|
|
|
return e.hash
|
|
|
|
}
|
|
|
|
|
|
|
|
// createHash creates hashes of the payload.
|
|
|
|
func (e *Extensible) createHash() {
|
2021-03-12 08:27:50 +00:00
|
|
|
buf := io.NewBufBinWriter()
|
|
|
|
e.encodeBinaryUnsigned(buf.BinWriter)
|
|
|
|
e.hash = hash.Sha256(buf.Bytes())
|
2021-01-13 15:12:40 +00:00
|
|
|
}
|