184 lines
4.0 KiB
Go
184 lines
4.0 KiB
Go
package shred
|
|
|
|
import (
|
|
"encoding/base64"
|
|
|
|
bin "github.com/gagliardetto/binary"
|
|
"github.com/gagliardetto/solana-go"
|
|
)
|
|
|
|
type LegacyCode struct {
|
|
Common CommonHeader
|
|
Payload []byte
|
|
}
|
|
|
|
const (
|
|
LegacyDataHeaderSize = 86
|
|
LegacyDataV2HeaderSize = 88
|
|
LegacyPayloadSize = 1057 // TODO where does this number come from?
|
|
LegacyV2PayloadSize = 1051 // TODO idk???
|
|
)
|
|
|
|
func LegacyCodeFromPayload(shred []byte) *LegacyCode {
|
|
panic("legacy shred code unimplemented")
|
|
}
|
|
|
|
func (s *LegacyCode) CommonHeader() *CommonHeader {
|
|
return &s.Common
|
|
}
|
|
|
|
func (s *LegacyCode) DataHeader() *DataHeader {
|
|
return nil
|
|
}
|
|
|
|
func (s *LegacyCode) Data() ([]byte, bool) {
|
|
return nil, false
|
|
}
|
|
|
|
func (s *LegacyCode) DataComplete() bool {
|
|
return false
|
|
}
|
|
|
|
// LegacyData is genesis-era shred data.
|
|
type LegacyData struct {
|
|
Common CommonHeader
|
|
Header DataHeader
|
|
Payload []byte
|
|
}
|
|
|
|
func LegacyDataFromPayload(shred []byte) *LegacyData {
|
|
data := new(LegacyData)
|
|
dec := bin.NewBinDecoder(shred)
|
|
if err := dec.Decode(&data.Common); err != nil {
|
|
return nil
|
|
}
|
|
if err := dec.Decode(&data.Header); err != nil {
|
|
return nil
|
|
}
|
|
if data.Common.Variant != LegacyDataID {
|
|
return nil
|
|
}
|
|
if len(shred) < LegacyDataHeaderSize {
|
|
return nil
|
|
}
|
|
// TODO Sanitize
|
|
data.Payload = make([]byte, LegacyDataHeaderSize+LegacyPayloadSize)
|
|
copy(data.Payload, shred)
|
|
return data
|
|
}
|
|
|
|
func (s *LegacyData) CommonHeader() *CommonHeader {
|
|
return &s.Common
|
|
}
|
|
|
|
func (s *LegacyData) DataHeader() *DataHeader {
|
|
return &s.Header
|
|
}
|
|
|
|
func (s *LegacyData) Data() ([]byte, bool) {
|
|
return s.Payload[LegacyDataHeaderSize : LegacyDataHeaderSize+LegacyPayloadSize], true
|
|
}
|
|
|
|
func (s *LegacyData) DataComplete() bool {
|
|
return s.Header.Flags&FlagDataCompleteShred == 1
|
|
}
|
|
|
|
func (s *LegacyData) ReferenceTick() uint8 {
|
|
return s.Header.Flags & FlagShredTickReferenceMask
|
|
}
|
|
|
|
func (s *LegacyData) MarshalYAML() (any, error) {
|
|
item := struct {
|
|
Signature solana.Signature
|
|
Variant uint8
|
|
Slot uint64
|
|
Index uint32
|
|
Version uint16
|
|
FECSetIndex uint32
|
|
Payload string
|
|
}{
|
|
Signature: s.Common.Signature,
|
|
Variant: s.Common.Variant,
|
|
Slot: s.Common.Slot,
|
|
Index: s.Common.Index,
|
|
Version: s.Common.Version,
|
|
FECSetIndex: s.Common.FECSetIndex,
|
|
Payload: base64.StdEncoding.EncodeToString(s.Payload),
|
|
}
|
|
return item, nil
|
|
}
|
|
|
|
// LegacyDataV2 is Q2 2020-era shred data.
|
|
type LegacyDataV2 struct {
|
|
Common CommonHeader
|
|
Header DataV2Header
|
|
Payload []byte
|
|
}
|
|
|
|
func LegacyDataV2FromPayload(shred []byte) *LegacyDataV2 {
|
|
data := new(LegacyDataV2)
|
|
dec := bin.NewBinDecoder(shred)
|
|
if err := dec.Decode(&data.Common); err != nil {
|
|
return nil
|
|
}
|
|
if err := dec.Decode(&data.Header); err != nil {
|
|
return nil
|
|
}
|
|
if data.Common.Variant != LegacyDataID {
|
|
return nil
|
|
}
|
|
if len(shred) < LegacyDataV2HeaderSize {
|
|
return nil
|
|
}
|
|
// TODO Sanitize
|
|
data.Payload = make([]byte, LegacyDataV2HeaderSize+LegacyV2PayloadSize)
|
|
copy(data.Payload, shred)
|
|
return data
|
|
}
|
|
|
|
func (s *LegacyDataV2) CommonHeader() *CommonHeader {
|
|
return &s.Common
|
|
}
|
|
|
|
func (s *LegacyDataV2) DataHeader() *DataV2Header {
|
|
return &s.Header
|
|
}
|
|
|
|
func (s *LegacyDataV2) Data() ([]byte, bool) {
|
|
if int(s.Header.Size) > len(s.Payload) {
|
|
return nil, false
|
|
}
|
|
return s.Payload[LegacyDataV2HeaderSize:s.Header.Size], true
|
|
}
|
|
|
|
func (s *LegacyDataV2) DataComplete() bool {
|
|
return s.Header.Flags&FlagDataCompleteShred == 1
|
|
}
|
|
|
|
func (s *LegacyDataV2) ReferenceTick() uint8 {
|
|
return s.Header.Flags & FlagShredTickReferenceMask
|
|
}
|
|
|
|
func (s *LegacyDataV2) MarshalYAML() (any, error) {
|
|
item := struct {
|
|
Signature solana.Signature
|
|
Variant uint8
|
|
Slot uint64
|
|
Index uint32
|
|
Version uint16
|
|
FECSetIndex uint32
|
|
Size uint16
|
|
Payload string
|
|
}{
|
|
Signature: s.Common.Signature,
|
|
Variant: s.Common.Variant,
|
|
Slot: s.Common.Slot,
|
|
Index: s.Common.Index,
|
|
Version: s.Common.Version,
|
|
FECSetIndex: s.Common.FECSetIndex,
|
|
Size: s.Header.Size,
|
|
Payload: base64.StdEncoding.EncodeToString(s.Payload),
|
|
}
|
|
return item, nil
|
|
}
|