Skip to content
Snippets Groups Projects
Commit 77b481b7 authored by capossele's avatar capossele
Browse files

:sparkles: adds DRNG ontology

parent 92bc053c
No related branches found
No related tags found
No related merge requests found
package collectiveBeacon
import (
"sync"
"github.com/iotaledger/hive.go/stringify"
drngPayload "github.com/iotaledger/goshimmer/packages/binary/drng/payload"
"github.com/iotaledger/goshimmer/packages/binary/drng/payload/header"
"github.com/iotaledger/goshimmer/packages/binary/marshalutil"
"github.com/iotaledger/goshimmer/packages/binary/tangle/model/transaction/payload"
)
type Payload struct {
//objectstorage.StorableObjectFlags
header header.Header
round uint64 // round of the current beacon
prevSignature []byte // collective signature of the previous beacon
signature []byte // collective signature of the current beacon
dpk []byte // distributed public key
bytes []byte
bytesMutex sync.RWMutex
}
func New(instanceID uint32, round uint64, prevSignature, signature, dpk []byte) *Payload {
return &Payload{
header: header.New(header.CollectiveBeaconType(), instanceID),
round: round,
prevSignature: prevSignature,
signature: signature,
dpk: dpk,
}
}
func (p *Payload) SubType() header.Type {
return p.header.PayloadType()
}
func (payload *Payload) Instance() uint32 {
return payload.header.Instance()
}
func (payload *Payload) Round() uint64 {
return payload.round
}
func (payload *Payload) PrevSignature() []byte {
return payload.prevSignature
}
func (payload *Payload) Signature() []byte {
return payload.signature
}
func (payload *Payload) DistributedPK() []byte {
return payload.dpk
}
// FromBytes parses the marshaled version of a Payload into an object.
// It either returns a new Payload or fills an optionally provided Payload with the parsed information.
func FromBytes(bytes []byte, optionalTargetObject ...*Payload) (result *Payload, err error, consumedBytes int) {
// determine the target object that will hold the unmarshaled information
switch len(optionalTargetObject) {
case 0:
result = &Payload{}
case 1:
result = optionalTargetObject[0]
default:
panic("too many arguments in call to OutputFromBytes")
}
// initialize helper
marshalUtil := marshalutil.New(bytes)
// read information that are required to identify the payload from the outside
if _, err = marshalUtil.ReadUint32(); err != nil {
return
}
if _, err = marshalUtil.ReadUint32(); err != nil {
return
}
// parse header
if result.header, err = header.Parse(marshalUtil); err != nil {
return
}
// parse round
if result.round, err = marshalUtil.ReadUint64(); err != nil {
return
}
// parse prevSignature
if result.prevSignature, err = marshalUtil.ReadBytes(SignatureSize); err != nil {
return
}
// parse current signature
if result.signature, err = marshalUtil.ReadBytes(SignatureSize); err != nil {
return
}
// parse distributed public key
if result.dpk, err = marshalUtil.ReadBytes(PublicKeySize); err != nil {
return
}
// return the number of bytes we processed
consumedBytes = marshalUtil.ReadOffset()
// store bytes, so we don't have to marshal manually
result.bytes = bytes[:consumedBytes]
return
}
func (payload *Payload) Bytes() (bytes []byte) {
// acquire lock for reading bytes
payload.bytesMutex.RLock()
// return if bytes have been determined already
if bytes = payload.bytes; bytes != nil {
defer payload.bytesMutex.RUnlock()
return
}
// switch to write lock
payload.bytesMutex.RUnlock()
payload.bytesMutex.Lock()
defer payload.bytesMutex.Unlock()
// return if bytes have been determined in the mean time
if bytes = payload.bytes; bytes != nil {
return
}
// marshal fields
payloadLength := header.Length + marshalutil.UINT64_SIZE + SignatureSize*2 + PublicKeySize
marshalUtil := marshalutil.New(marshalutil.UINT32_SIZE + marshalutil.UINT32_SIZE + payloadLength)
marshalUtil.WriteUint32(drngPayload.Type)
marshalUtil.WriteUint32(uint32(payloadLength))
marshalUtil.WriteBytes(payload.header.Bytes())
marshalUtil.WriteUint64(payload.Round())
marshalUtil.WriteBytes(payload.PrevSignature())
marshalUtil.WriteBytes(payload.Signature())
marshalUtil.WriteBytes(payload.DistributedPK())
bytes = marshalUtil.Bytes()
// store result
payload.bytes = bytes
return
}
func (payload *Payload) String() string {
return stringify.Struct("Payload",
stringify.StructField("type", payload.SubType()),
stringify.StructField("instance", payload.Instance()),
stringify.StructField("round", payload.Round()),
stringify.StructField("prevSignature", payload.PrevSignature()),
stringify.StructField("signature", payload.Signature()),
stringify.StructField("distributedPK", payload.DistributedPK()),
)
}
// region Payload implementation ///////////////////////////////////////////////////////////////////////////////////////
func (payload *Payload) GetType() payload.Type {
return drngPayload.Type
}
func (payload *Payload) MarshalBinary() (bytes []byte, err error) {
return payload.Bytes(), nil
}
func (payload *Payload) UnmarshalBinary(data []byte) (err error) {
_, err, _ = FromBytes(data, payload)
return
}
// func init() {
// payload.RegisterType(drngPayload.Type, func(data []byte) (payload payload.Payload, err error) {
// payload = &Payload{}
// err = payload.UnmarshalBinary(data)
// return
// })
// }
// define contract (ensure that the struct fulfills the corresponding interface)
var _ payload.Payload = &Payload{}
// // endregion ///////////////////////////////////////////////////////////////////////////////////////////////////////////
package collectiveBeacon
import (
"testing"
"github.com/iotaledger/goshimmer/packages/binary/drng/payload/header"
"github.com/iotaledger/goshimmer/packages/binary/marshalutil"
"github.com/stretchr/testify/require"
)
func TestParse(t *testing.T) {
header := header.New(header.CollectiveBeaconType(), 0)
payload := New(header.Instance(),
0,
[]byte("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"), // prevSignature
[]byte("BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"), // signature
[]byte("CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC")) // distributed PK
bytes := payload.Bytes()
marshalUtil := marshalutil.New(bytes)
parsedpayload, err := marshalUtil.Parse(func(data []byte) (interface{}, error, int) { return FromBytes(data) })
require.NoError(t, err)
cb := parsedpayload.(*Payload)
require.Equal(t, payload.SubType(), cb.SubType())
require.Equal(t, payload.Instance(), cb.Instance())
require.Equal(t, payload.Round(), cb.Round())
require.Equal(t, payload.PrevSignature(), cb.PrevSignature())
require.Equal(t, payload.Signature(), cb.Signature())
require.Equal(t, payload.DistributedPK(), cb.DistributedPK())
}
package collectiveBeacon
const (
// BLS Signature size in bytes
SignatureSize = 32
// BLS Public Key size in bytes
PublicKeySize = 32
)
package header
import (
"github.com/iotaledger/goshimmer/packages/binary/marshalutil"
)
type Type = byte
type payloadType struct {
CollectiveBeacon Type
}
var drngTypes = &payloadType{
CollectiveBeacon: Type(1),
}
const Length = 5
func CollectiveBeaconType() Type {
return drngTypes.CollectiveBeacon
}
type Header struct {
payloadType Type // message type
instanceID uint32 // identifier of the dRAND instance
}
func New(payloadType Type, instanceID uint32) Header {
return Header{
payloadType: payloadType,
instanceID: instanceID,
}
}
func (h Header) PayloadType() Type {
return h.payloadType
}
func (h Header) Instance() uint32 {
return h.instanceID
}
// Parse is a wrapper for simplified unmarshaling in a byte stream using the marshalUtil package.
func Parse(marshalUtil *marshalutil.MarshalUtil) (Header, error) {
if header, err := marshalUtil.Parse(func(data []byte) (interface{}, error, int) { return FromBytes(data) }); err != nil {
return Header{}, err
} else {
return header.(Header), nil
}
}
// FromBytes unmarshals a header from a sequence of bytes.
// It either creates a new header or fills the optionally provided object with the parsed information.
func FromBytes(bytes []byte, optionalTargetObject ...*Header) (result Header, err error, consumedBytes int) {
// determine the target object that will hold the unmarshaled information
var targetObject *Header
switch len(optionalTargetObject) {
case 0:
targetObject = &result
case 1:
targetObject = optionalTargetObject[0]
default:
panic("too many arguments in call to FromBytes")
}
// initialize helper
marshalUtil := marshalutil.New(bytes)
// read payload type from bytes
if targetObject.payloadType, err = marshalUtil.ReadByte(); err != nil {
return
}
// read instance ID from bytes
if targetObject.instanceID, err = marshalUtil.ReadUint32(); err != nil {
return
}
// copy result if we have provided a target object
result = *targetObject
// return the number of bytes we processed
consumedBytes = marshalUtil.ReadOffset()
return
}
func (header *Header) Bytes() (bytes []byte) {
// initialize helper
marshalUtil := marshalutil.New()
// marshal the payload specific information
marshalUtil.WriteByte(header.PayloadType())
marshalUtil.WriteUint32(header.Instance())
bytes = marshalUtil.Bytes()
return
}
package header
import (
"testing"
"github.com/iotaledger/goshimmer/packages/binary/marshalutil"
"github.com/stretchr/testify/require"
)
func TestParse(t *testing.T) {
header := New(CollectiveBeaconType(), 0)
bytes := header.Bytes()
marshalUtil := marshalutil.New(bytes)
parsedHeader, err := Parse(marshalUtil)
require.NoError(t, err)
require.Equal(t, header, parsedHeader)
}
package payload
import (
"sync"
"github.com/iotaledger/goshimmer/packages/binary/drng/payload/header"
"github.com/iotaledger/goshimmer/packages/binary/marshalutil"
"github.com/iotaledger/goshimmer/packages/binary/tangle/model/transaction/payload"
"github.com/iotaledger/hive.go/stringify"
)
type Payload struct {
header header.Header
data []byte
bytes []byte
bytesMutex sync.RWMutex
}
func New(header header.Header, data []byte) *Payload {
return &Payload{
header: header,
data: data,
}
}
func (p *Payload) SubType() header.Type {
return p.header.PayloadType()
}
func (payload *Payload) Instance() uint32 {
return payload.header.Instance()
}
func (payload *Payload) Data() []byte {
return payload.data
}
// FromBytes parses the marshaled version of a Payload into an object.
// It either returns a new Payload or fills an optionally provided Payload with the parsed information.
func FromBytes(bytes []byte, optionalTargetObject ...*Payload) (result *Payload, err error, consumedBytes int) {
// determine the target object that will hold the unmarshaled information
switch len(optionalTargetObject) {
case 0:
result = &Payload{}
case 1:
result = optionalTargetObject[0]
default:
panic("too many arguments in call to OutputFromBytes")
}
// initialize helper
marshalUtil := marshalutil.New(bytes)
// read information that are required to identify the payload from the outside
if _, err = marshalUtil.ReadUint32(); err != nil {
return
}
len, err := marshalUtil.ReadUint32()
if err != nil {
return
}
// parse header
if result.header, err = header.Parse(marshalUtil); err != nil {
return
}
// parse data
if result.data, err = marshalUtil.ReadBytes(int(len - header.Length)); err != nil {
return
}
// store bytes, so we don't have to marshal manually
result.bytes = bytes[:consumedBytes]
return
}
func (payload *Payload) Bytes() (bytes []byte) {
// acquire lock for reading bytes
payload.bytesMutex.RLock()
// return if bytes have been determined already
if bytes = payload.bytes; bytes != nil {
defer payload.bytesMutex.RUnlock()
return
}
// switch to write lock
payload.bytesMutex.RUnlock()
payload.bytesMutex.Lock()
defer payload.bytesMutex.Unlock()
// return if bytes have been determined in the mean time
if bytes = payload.bytes; bytes != nil {
return
}
// initialize helper
marshalUtil := marshalutil.New()
// marshal the payload specific information
marshalUtil.WriteUint32(Type)
marshalUtil.WriteUint32(uint32(len(payload.data) + header.Length))
marshalUtil.WriteBytes(payload.header.Bytes())
marshalUtil.WriteBytes(payload.data[:])
bytes = marshalUtil.Bytes()
return
}
func (payload *Payload) String() string {
return stringify.Struct("Payload",
stringify.StructField("type", payload.SubType()),
stringify.StructField("instance", payload.Instance()),
stringify.StructField("data", payload.Data()),
)
}
// region Payload implementation ///////////////////////////////////////////////////////////////////////////////////////
var Type = payload.Type(111)
func (payload *Payload) GetType() payload.Type {
return Type
}
func (payload *Payload) MarshalBinary() (bytes []byte, err error) {
return payload.Bytes(), nil
}
func (payload *Payload) UnmarshalBinary(data []byte) (err error) {
_, err, _ = FromBytes(data, payload)
return
}
func init() {
payload.RegisterType(Type, func(data []byte) (payload payload.Payload, err error) {
payload = &Payload{}
err = payload.UnmarshalBinary(data)
return
})
}
// define contract (ensure that the struct fulfills the corresponding interface)
var _ payload.Payload = &Payload{}
// // endregion ///////////////////////////////////////////////////////////////////////////////////////////////////////////
package payload
import (
"testing"
"github.com/iotaledger/goshimmer/packages/binary/drng/payload/header"
"github.com/iotaledger/goshimmer/packages/binary/marshalutil"
"github.com/stretchr/testify/require"
)
func TestParse(t *testing.T) {
header := header.New(header.CollectiveBeaconType(), 0)
data := []byte("test")
payload := New(header, data)
bytes := payload.Bytes()
marshalUtil := marshalutil.New(bytes)
parsedpayload, err := marshalUtil.Parse(func(data []byte) (interface{}, error, int) { return FromBytes(data) })
require.NoError(t, err)
cb := parsedpayload.(*Payload)
require.Equal(t, payload.SubType(), cb.SubType())
require.Equal(t, payload.Instance(), cb.Instance())
require.Equal(t, payload.Data(), cb.Data())
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment