Skip to content
Snippets Groups Projects
Unverified Commit 37125323 authored by Angelo Capossele's avatar Angelo Capossele Committed by GitHub
Browse files

dRNG refactor (#727)

* :recycle: Flatten drng package

* :rotating_light: Fix linter warnings

* :recycle: Refactor dRNG plugin, API and dashboard

* :white_check_mark:

 Address review comments

* refactor: Rename Parse_ functions to _FromMarshalUtil for consistency

* fix: Fix typo

* fix: Fix comments

Co-authored-by: default avatarjkrvivian <jkrvivian@gmail.com>
parent 659076d3
No related branches found
No related tags found
No related merge requests found
Showing
with 243 additions and 230 deletions
package drng
import (
"github.com/iotaledger/goshimmer/packages/binary/drng/state"
)
// DRNG holds the state and events of a drng instance.
type DRNG struct {
State *state.State // The state of the DRNG.
Events *Event // The events fired on the DRNG.
}
// New creates a new DRNG instance.
func New(setters ...state.Option) *DRNG {
return &DRNG{
State: state.New(setters...),
Events: newEvent(),
}
}
package drng
import (
"github.com/iotaledger/goshimmer/packages/binary/drng/state"
cbEvents "github.com/iotaledger/goshimmer/packages/binary/drng/subtypes/collectivebeacon/events"
"github.com/iotaledger/hive.go/events"
)
// Event holds the different events triggered by a DRNG instance.
type Event struct {
// Collective Beacon is triggered each time we receive a new CollectiveBeacon message.
CollectiveBeacon *events.Event
// Randomness is triggered each time we receive a new and valid CollectiveBeacon message.
Randomness *events.Event
}
func newEvent() *Event {
return &Event{
CollectiveBeacon: events.NewEvent(cbEvents.CollectiveBeaconReceived),
Randomness: events.NewEvent(randomnessReceived),
}
}
func randomnessReceived(handler interface{}, params ...interface{}) {
handler.(func(state.Randomness))(params[0].(state.Randomness))
}
package state
// Options define state options of a DRNG.
type Options struct {
// The initial committee of the DRNG.
Committee *Committee
// The initial randomness of the DRNG.
Randomness *Randomness
}
// Option is a function which sets the given option.
type Option func(*Options)
// SetCommittee sets the initial committee
func SetCommittee(c *Committee) Option {
return func(args *Options) {
args.Committee = c
}
}
// SetRandomness sets the initial randomness
func SetRandomness(r *Randomness) Option {
return func(args *Options) {
args.Randomness = r
}
}
package collectivebeacon
package drng
import (
"bytes"
......@@ -7,8 +7,6 @@ import (
"github.com/drand/drand/chain"
"github.com/drand/drand/key"
"github.com/iotaledger/goshimmer/packages/binary/drng/state"
"github.com/iotaledger/goshimmer/packages/binary/drng/subtypes/collectivebeacon/events"
"github.com/iotaledger/hive.go/crypto/ed25519"
)
......@@ -30,10 +28,10 @@ var (
// ProcessBeacon performs the following tasks:
// - verify that we have a valid random
// - update drng state
func ProcessBeacon(drng *state.State, cb *events.CollectiveBeaconEvent) error {
func ProcessBeacon(state *State, cb *CollectiveBeaconEvent) error {
// verify that we have a valid random
if err := VerifyCollectiveBeacon(drng, cb); err != nil {
if err := VerifyCollectiveBeacon(state, cb); err != nil {
//TODO: handle error
return err
}
......@@ -44,45 +42,45 @@ func ProcessBeacon(drng *state.State, cb *events.CollectiveBeaconEvent) error {
//TODO: handle error
return err
}
newRandomness := &state.Randomness{
newRandomness := &Randomness{
Round: cb.Round,
Randomness: randomness,
Timestamp: cb.Timestamp,
}
drng.UpdateRandomness(newRandomness)
state.UpdateRandomness(newRandomness)
return nil
}
// VerifyCollectiveBeacon verifies against a given state that
// the given CollectiveBeaconEvent contains a valid beacon.
func VerifyCollectiveBeacon(state *state.State, data *events.CollectiveBeaconEvent) error {
func VerifyCollectiveBeacon(state *State, cb *CollectiveBeaconEvent) error {
if state == nil {
return ErrNilState
}
if data == nil {
if cb == nil {
return ErrNilData
}
if err := verifyIssuer(state, data.IssuerPublicKey); err != nil {
if err := verifyIssuer(state, cb.IssuerPublicKey); err != nil {
return err
}
if !bytes.Equal(data.Dpk, state.Committee().DistributedPK) {
if !bytes.Equal(cb.Dpk, state.Committee().DistributedPK) {
return ErrDistributedPubKeyMismatch
}
if data.Round <= state.Randomness().Round {
if cb.Round <= state.Randomness().Round {
return ErrInvalidRound
}
if data.InstanceID != state.Committee().InstanceID {
if cb.InstanceID != state.Committee().InstanceID {
return ErrInstanceIDMismatch
}
if err := verifySignature(data); err != nil {
if err := verifySignature(cb); err != nil {
return err
}
......@@ -90,7 +88,7 @@ func VerifyCollectiveBeacon(state *state.State, data *events.CollectiveBeaconEve
}
// verifyIssuer checks the given issuer is a member of the committee.
func verifyIssuer(state *state.State, issuer ed25519.PublicKey) error {
func verifyIssuer(state *State, issuer ed25519.PublicKey) error {
for _, member := range state.Committee().Identities {
if member == issuer {
return nil
......@@ -100,15 +98,15 @@ func verifyIssuer(state *state.State, issuer ed25519.PublicKey) error {
}
// verifySignature checks the current signature against the distributed public key.
func verifySignature(data *events.CollectiveBeaconEvent) error {
func verifySignature(cb *CollectiveBeaconEvent) error {
dpk := key.KeyGroup.Point()
if err := dpk.UnmarshalBinary(data.Dpk); err != nil {
if err := dpk.UnmarshalBinary(cb.Dpk); err != nil {
return err
}
msg := chain.Message(data.Round, data.PrevSignature)
msg := chain.Message(cb.Round, cb.PrevSignature)
if err := key.Scheme.VerifyRecovered(dpk, msg, data.Signature); err != nil {
if err := key.Scheme.VerifyRecovered(dpk, msg, cb.Signature); err != nil {
return err
}
......
package payload
package drng
import (
"fmt"
......@@ -6,15 +6,13 @@ import (
"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/tangle"
"github.com/iotaledger/hive.go/marshalutil"
)
// Payload is a collective beacon payload.
type Payload struct {
header.Header
// CollectiveBeaconPayload is a collective beacon payload.
type CollectiveBeaconPayload struct {
Header
// Round of the current beacon
Round uint64
......@@ -29,10 +27,10 @@ type Payload struct {
bytesMutex sync.RWMutex
}
// New creates a new collective beacon payload.
func New(instanceID uint32, round uint64, prevSignature, signature, dpk []byte) *Payload {
return &Payload{
Header: header.New(header.TypeCollectiveBeacon, instanceID),
// NewCollectiveBeaconPayload creates a new collective beacon payload.
func NewCollectiveBeaconPayload(instanceID uint32, round uint64, prevSignature, signature, dpk []byte) *CollectiveBeaconPayload {
return &CollectiveBeaconPayload{
Header: NewHeader(TypeCollectiveBeacon, instanceID),
Round: round,
PrevSignature: prevSignature,
Signature: signature,
......@@ -40,21 +38,21 @@ func New(instanceID uint32, round uint64, prevSignature, signature, dpk []byte)
}
}
// Parse is a wrapper for simplified unmarshaling in a byte stream using the marshalUtil package.
func Parse(marshalUtil *marshalutil.MarshalUtil) (*Payload, error) {
unmarshalledPayload, err := marshalUtil.Parse(func(data []byte) (interface{}, int, error) { return FromBytes(data) })
// CollectiveBeaconPayloadFromMarshalUtil is a wrapper for simplified unmarshaling in a byte stream using the marshalUtil package.
func CollectiveBeaconPayloadFromMarshalUtil(marshalUtil *marshalutil.MarshalUtil) (*CollectiveBeaconPayload, error) {
unmarshalledPayload, err := marshalUtil.Parse(func(data []byte) (interface{}, int, error) { return CollectiveBeaconPayloadFromBytes(data) })
if err != nil {
err = fmt.Errorf("failed to parse collective beacon payload: %w", err)
return nil, err
}
_payload := unmarshalledPayload.(*Payload)
_payload := unmarshalledPayload.(*CollectiveBeaconPayload)
return _payload, nil
}
// FromBytes parses the marshaled version of a Payload into an object.
// CollectiveBeaconPayloadFromBytes 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) (result *Payload, consumedBytes int, err error) {
func CollectiveBeaconPayloadFromBytes(bytes []byte) (result *CollectiveBeaconPayload, consumedBytes int, err error) {
// initialize helper
marshalUtil := marshalutil.New(bytes)
......@@ -69,8 +67,8 @@ func FromBytes(bytes []byte) (result *Payload, consumedBytes int, err error) {
}
// parse header
result = &Payload{}
if result.Header, err = header.Parse(marshalUtil); err != nil {
result = &CollectiveBeaconPayload{}
if result.Header, err = HeaderFromMarshalUtil(marshalUtil); err != nil {
err = fmt.Errorf("failed to parse header of collective beacon payload: %w", err)
return
}
......@@ -109,7 +107,7 @@ func FromBytes(bytes []byte) (result *Payload, consumedBytes int, err error) {
}
// Bytes returns the collective beacon payload bytes.
func (p *Payload) Bytes() (bytes []byte) {
func (p *CollectiveBeaconPayload) Bytes() (bytes []byte) {
// acquire lock for reading bytes
p.bytesMutex.RLock()
......@@ -130,10 +128,10 @@ func (p *Payload) Bytes() (bytes []byte) {
}
// marshal fields
payloadLength := header.Length + marshalutil.UINT64_SIZE + SignatureSize*2 + PublicKeySize
payloadLength := HeaderLength + marshalutil.UINT64_SIZE + SignatureSize*2 + PublicKeySize
marshalUtil := marshalutil.New(marshalutil.UINT32_SIZE + marshalutil.UINT32_SIZE + payloadLength)
marshalUtil.WriteUint32(uint32(payloadLength))
marshalUtil.WriteUint32(drngPayload.Type)
marshalUtil.WriteUint32(PayloadType)
marshalUtil.WriteBytes(p.Header.Bytes())
marshalUtil.WriteUint64(p.Round)
marshalUtil.WriteBytes(p.PrevSignature)
......@@ -148,8 +146,8 @@ func (p *Payload) Bytes() (bytes []byte) {
return
}
func (p *Payload) String() string {
return stringify.Struct("Payload",
func (p *CollectiveBeaconPayload) String() string {
return stringify.Struct("CollectiveBeaconPayload",
stringify.StructField("type", uint64(p.Header.PayloadType)),
stringify.StructField("instance", uint64(p.Header.InstanceID)),
stringify.StructField("round", p.Round),
......@@ -162,12 +160,12 @@ func (p *Payload) String() string {
// region Payload implementation ///////////////////////////////////////////////////////////////////////////////////////
// Type returns the collective beacon payload type.
func (p *Payload) Type() tangle.PayloadType {
return drngPayload.Type
func (p *CollectiveBeaconPayload) Type() tangle.PayloadType {
return PayloadType
}
// Marshal marshals the collective beacon payload into bytes.
func (p *Payload) Marshal() (bytes []byte, err error) {
func (p *CollectiveBeaconPayload) Marshal() (bytes []byte, err error) {
return p.Bytes(), nil
}
......
package payload
package drng
import (
"testing"
"github.com/iotaledger/goshimmer/packages/binary/drng/payload/header"
"github.com/iotaledger/hive.go/marshalutil"
"github.com/stretchr/testify/require"
)
func dummyPayload() *Payload {
header := header.New(header.TypeCollectiveBeacon, 0)
return New(header.InstanceID,
func dummyCollectiveBeaconPayload() *CollectiveBeaconPayload {
header := NewHeader(TypeCollectiveBeacon, 0)
return NewCollectiveBeaconPayload(header.InstanceID,
0,
[]byte("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"), // prevSignature
[]byte("BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"), // signature
......@@ -18,11 +17,11 @@ func dummyPayload() *Payload {
}
func TestParse(t *testing.T) {
payload := dummyPayload()
payload := dummyCollectiveBeaconPayload()
bytes := payload.Bytes()
marshalUtil := marshalutil.New(bytes)
parsedPayload, err := Parse(marshalUtil)
parsedPayload, err := CollectiveBeaconPayloadFromMarshalUtil(marshalUtil)
require.NoError(t, err)
require.Equal(t, payload.Header.PayloadType, parsedPayload.Header.PayloadType)
......@@ -33,7 +32,7 @@ func TestParse(t *testing.T) {
require.Equal(t, payload.Dpk, parsedPayload.Dpk)
}
func TestString(t *testing.T) {
func TestCollectiveBeaconPayloadString(t *testing.T) {
payload := dummyPayload()
_ = payload.String()
}
package collectivebeacon
package drng
import (
"encoding/hex"
......@@ -9,20 +9,13 @@ import (
"github.com/drand/drand/key"
"github.com/drand/kyber/share"
"github.com/drand/kyber/util/random"
"github.com/iotaledger/goshimmer/packages/binary/drng/state"
"github.com/iotaledger/goshimmer/packages/binary/drng/subtypes/collectivebeacon/events"
"github.com/iotaledger/goshimmer/packages/binary/drng/subtypes/collectivebeacon/payload"
"github.com/iotaledger/hive.go/crypto/ed25519"
"github.com/stretchr/testify/require"
)
var (
eventTest *events.CollectiveBeaconEvent
prevSignatureTest []byte
signatureTest []byte
dpkTest []byte
issuerPK ed25519.PublicKey
stateTest *state.State
eventTest *CollectiveBeaconEvent
stateTest *State
)
func init() {
......@@ -33,7 +26,7 @@ func init() {
kp := ed25519.GenerateKeyPair()
issuerPK = kp.PublicKey
eventTest = &events.CollectiveBeaconEvent{
eventTest = &CollectiveBeaconEvent{
IssuerPublicKey: issuerPK,
InstanceID: 1,
Round: 1,
......@@ -42,8 +35,8 @@ func init() {
Dpk: dpkTest,
}
stateTest = state.New(state.SetCommittee(
&state.Committee{
stateTest = NewState(SetCommittee(
&Committee{
InstanceID: 1,
Threshold: 3,
Identities: []ed25519.PublicKey{issuerPK},
......@@ -70,7 +63,7 @@ func TestDkgShares(t *testing.T) {
dkgShares(t, 5, 3)
}
func dkgShares(t *testing.T, n, threshold int) *payload.Payload {
func dkgShares(t *testing.T, n, threshold int) *CollectiveBeaconPayload {
var priPoly *share.PriPoly
var pubPoly *share.PubPoly
var err error
......@@ -137,5 +130,5 @@ func dkgShares(t *testing.T, n, threshold int) *payload.Payload {
log.Println(hex.EncodeToString(newSig))
log.Println(hex.EncodeToString(dpk))
return payload.New(1, 1, sig, newSig, dpk)
return NewCollectiveBeaconPayload(1, 1, sig, newSig, dpk)
}
package payload
package drng
const (
// SignatureSize defines the BLS Signature size in bytes.
......
......@@ -4,27 +4,22 @@ import (
"errors"
"time"
"github.com/iotaledger/goshimmer/packages/binary/drng/payload"
"github.com/iotaledger/goshimmer/packages/binary/drng/payload/header"
"github.com/iotaledger/goshimmer/packages/binary/drng/subtypes/collectivebeacon"
"github.com/iotaledger/goshimmer/packages/binary/drng/subtypes/collectivebeacon/events"
cb "github.com/iotaledger/goshimmer/packages/binary/drng/subtypes/collectivebeacon/payload"
"github.com/iotaledger/hive.go/crypto/ed25519"
"github.com/iotaledger/hive.go/marshalutil"
)
// Dispatch parses a DRNG message and process it based on its subtype
func (drng *DRNG) Dispatch(issuer ed25519.PublicKey, timestamp time.Time, payload *payload.Payload) error {
switch payload.Header.PayloadType {
case header.TypeCollectiveBeacon:
// Dispatch parses a DRNG message and processes it based on its subtype
func (d *DRNG) Dispatch(issuer ed25519.PublicKey, timestamp time.Time, payload *Payload) error {
switch payload.PayloadType {
case TypeCollectiveBeacon:
// parse as CollectiveBeaconType
marshalUtil := marshalutil.New(payload.Bytes())
parsedPayload, err := cb.Parse(marshalUtil)
parsedPayload, err := CollectiveBeaconPayloadFromMarshalUtil(marshalUtil)
if err != nil {
return err
}
// trigger CollectiveBeacon Event
cbEvent := &events.CollectiveBeaconEvent{
cbEvent := &CollectiveBeaconEvent{
IssuerPublicKey: issuer,
Timestamp: timestamp,
InstanceID: parsedPayload.Header.InstanceID,
......@@ -33,15 +28,15 @@ func (drng *DRNG) Dispatch(issuer ed25519.PublicKey, timestamp time.Time, payloa
Signature: parsedPayload.Signature,
Dpk: parsedPayload.Dpk,
}
drng.Events.CollectiveBeacon.Trigger(cbEvent)
d.Events.CollectiveBeacon.Trigger(cbEvent)
// process collectiveBeacon
if err := collectivebeacon.ProcessBeacon(drng.State, cbEvent); err != nil {
if err := ProcessBeacon(d.State, cbEvent); err != nil {
return err
}
// trigger RandomnessEvent
drng.Events.Randomness.Trigger(drng.State.Randomness())
d.Events.Randomness.Trigger(d.State.Randomness())
return nil
......
......@@ -5,11 +5,6 @@ import (
"testing"
"time"
"github.com/iotaledger/goshimmer/packages/binary/drng/payload"
"github.com/iotaledger/goshimmer/packages/binary/drng/payload/header"
"github.com/iotaledger/goshimmer/packages/binary/drng/state"
"github.com/iotaledger/goshimmer/packages/binary/drng/subtypes/collectivebeacon"
cbPayload "github.com/iotaledger/goshimmer/packages/binary/drng/subtypes/collectivebeacon/payload"
"github.com/iotaledger/hive.go/crypto/ed25519"
"github.com/iotaledger/hive.go/marshalutil"
"github.com/stretchr/testify/require"
......@@ -20,9 +15,9 @@ var (
signatureTest []byte
dpkTest []byte
issuerPK ed25519.PublicKey
committeeTest *state.Committee
committeeTest *Committee
timestampTest time.Time
randomnessTest *state.Randomness
randomnessTest *Randomness
)
func init() {
......@@ -31,8 +26,8 @@ func init() {
dpkTest, _ = hex.DecodeString("80b319dbf164d852cdac3d86f0b362e0131ddeae3d87f6c3c5e3b6a9de384093b983db88f70e2008b0e945657d5980e2")
timestampTest = time.Now()
rand, _ := collectivebeacon.ExtractRandomness(signatureTest)
randomnessTest = &state.Randomness{
rand, _ := ExtractRandomness(signatureTest)
randomnessTest = &Randomness{
Round: 1,
Randomness: rand,
Timestamp: timestampTest,
......@@ -41,7 +36,7 @@ func init() {
kp := ed25519.GenerateKeyPair()
issuerPK = kp.PublicKey
committeeTest = &state.Committee{
committeeTest = &Committee{
InstanceID: 1,
Threshold: 3,
Identities: []ed25519.PublicKey{issuerPK},
......@@ -49,9 +44,9 @@ func init() {
}
}
func dummyPayload() *cbPayload.Payload {
header := header.New(header.TypeCollectiveBeacon, 1)
return cbPayload.New(header.InstanceID,
func testPayload() *CollectiveBeaconPayload {
header := NewHeader(TypeCollectiveBeacon, 1)
return NewCollectiveBeaconPayload(header.InstanceID,
1,
prevSignatureTest,
signatureTest,
......@@ -59,11 +54,11 @@ func dummyPayload() *cbPayload.Payload {
}
func TestDispatcher(t *testing.T) {
marshalUtil := marshalutil.New(dummyPayload().Bytes())
parsedPayload, err := payload.Parse(marshalUtil)
marshalUtil := marshalutil.New(testPayload().Bytes())
parsedPayload, err := PayloadFromMarshalUtil(marshalUtil)
require.NoError(t, err)
drng := New(state.SetCommittee(committeeTest))
drng := New(SetCommittee(committeeTest))
err = drng.Dispatch(issuerPK, timestampTest, parsedPayload)
require.NoError(t, err)
require.Equal(t, *randomnessTest, drng.State.Randomness())
......
package state
package drng
import (
"encoding/binary"
......@@ -8,6 +8,45 @@ import (
"github.com/iotaledger/hive.go/crypto/ed25519"
)
// DRNG holds the state and events of a drng instance.
type DRNG struct {
State *State // The state of the DRNG.
Events *Event // The events fired on the DRNG.
}
// New creates a new DRNG instance.
func New(setters ...Option) *DRNG {
return &DRNG{
State: NewState(setters...),
Events: newEvent(),
}
}
// Options define state options of a DRNG.
type Options struct {
// The initial committee of the DRNG.
Committee *Committee
// The initial randomness of the DRNG.
Randomness *Randomness
}
// Option is a function which sets the given option.
type Option func(*Options)
// SetCommittee sets the initial committee
func SetCommittee(c *Committee) Option {
return func(args *Options) {
args.Committee = c
}
}
// SetRandomness sets the initial randomness
func SetRandomness(r *Randomness) Option {
return func(args *Options) {
args.Randomness = r
}
}
// Randomness defines the current randomness state of a DRNG instance.
type Randomness struct {
// Round holds the current DRNG round.
......@@ -43,8 +82,8 @@ type State struct {
mutex sync.RWMutex
}
// New creates a new State with the given optional options
func New(setters ...Option) *State {
// NewState creates a new State with the given optional options
func NewState(setters ...Option) *State {
args := &Options{}
for _, setter := range setters {
......
package events
package drng
import (
"time"
"github.com/iotaledger/hive.go/crypto/ed25519"
"github.com/iotaledger/hive.go/events"
)
// CollectiveBeaconEvent holds data about a collective beacon event.
......@@ -28,3 +29,22 @@ type CollectiveBeaconEvent struct {
func CollectiveBeaconReceived(handler interface{}, params ...interface{}) {
handler.(func(*CollectiveBeaconEvent))(params[0].(*CollectiveBeaconEvent))
}
// Event holds the different events triggered by a DRNG instance.
type Event struct {
// Collective Beacon is triggered each time we receive a new CollectiveBeacon message.
CollectiveBeacon *events.Event
// Randomness is triggered each time we receive a new and valid CollectiveBeacon message.
Randomness *events.Event
}
func newEvent() *Event {
return &Event{
CollectiveBeacon: events.NewEvent(CollectiveBeaconReceived),
Randomness: events.NewEvent(randomnessReceived),
}
}
func randomnessReceived(handler interface{}, params ...interface{}) {
handler.(func(Randomness))(params[0].(Randomness))
}
package events
package drng
import (
"testing"
......
package header
package drng
import (
"github.com/iotaledger/hive.go/marshalutil"
)
// Type defines the data model of a DRNG payload type
// Type defines a drng payload type
type Type = byte
const (
......@@ -12,8 +12,8 @@ const (
TypeCollectiveBeacon Type = 1
)
// Length defines the length of a DRNG header
const Length = 5
// HeaderLength defines the length of a DRNG header
const HeaderLength = 5
// Header defines defines a DRNG payload header
type Header struct {
......@@ -21,26 +21,26 @@ type Header struct {
InstanceID uint32 // identifier of the DRNG instance
}
// New creates a new DRNG payload header for the given type and instance id.
func New(payloadType Type, instanceID uint32) Header {
// NewHeader creates a new DRNG payload header for the given type and instance id.
func NewHeader(payloadType Type, instanceID uint32) Header {
return Header{
PayloadType: payloadType,
InstanceID: instanceID,
}
}
// Parse is a wrapper for simplified unmarshaling in a byte stream using the marshalUtil package.
func Parse(marshalUtil *marshalutil.MarshalUtil) (Header, error) {
header, err := marshalUtil.Parse(func(data []byte) (interface{}, int, error) { return FromBytes(data) })
// HeaderFromMarshalUtil is a wrapper for simplified unmarshaling in a byte stream using the marshalUtil package.
func HeaderFromMarshalUtil(marshalUtil *marshalutil.MarshalUtil) (Header, error) {
header, err := marshalUtil.Parse(func(data []byte) (interface{}, int, error) { return HeaderFromBytes(data) })
if err != nil {
return Header{}, err
}
return header.(Header), nil
}
// FromBytes unmarshals a header from a sequence of bytes.
// HeaderFromBytes 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, consumedBytes int, err error) {
func HeaderFromBytes(bytes []byte, optionalTargetObject ...*Header) (result Header, consumedBytes int, err error) {
// determine the target object that will hold the unmarshaled information
var targetObject *Header
switch len(optionalTargetObject) {
......@@ -75,13 +75,13 @@ func FromBytes(bytes []byte, optionalTargetObject ...*Header) (result Header, co
}
// Bytes returns the header in serialized bytes form.
func (header *Header) Bytes() (bytes []byte) {
func (h *Header) Bytes() (bytes []byte) {
// initialize helper
marshalUtil := marshalutil.New()
// marshal the payload specific information
marshalUtil.WriteByte(header.PayloadType)
marshalUtil.WriteUint32(header.InstanceID)
marshalUtil.WriteByte(h.PayloadType)
marshalUtil.WriteUint32(h.InstanceID)
bytes = marshalUtil.Bytes()
......
package header
package drng
import (
"testing"
......@@ -7,12 +7,12 @@ import (
"github.com/stretchr/testify/require"
)
func TestParse(t *testing.T) {
header := New(TypeCollectiveBeacon, 0)
func TestHeaderFromMarshalUtil(t *testing.T) {
header := NewHeader(TypeCollectiveBeacon, 0)
bytes := header.Bytes()
marshalUtil := marshalutil.New(bytes)
parsedHeader, err := Parse(marshalUtil)
parsedHeader, err := HeaderFromMarshalUtil(marshalUtil)
require.NoError(t, err)
require.Equal(t, header, parsedHeader)
......
package payload
package drng
import (
"fmt"
"sync"
"github.com/iotaledger/goshimmer/packages/binary/drng/payload/header"
"github.com/iotaledger/goshimmer/packages/tangle"
"github.com/iotaledger/hive.go/marshalutil"
"github.com/iotaledger/hive.go/stringify"
......@@ -17,23 +16,23 @@ const (
// Payload defines a DRNG payload.
type Payload struct {
header.Header
Header
Data []byte
bytes []byte
bytesMutex sync.RWMutex
}
// New creates a new DRNG payload.
func New(header header.Header, data []byte) *Payload {
// NewPayload creates a new DRNG payload.
func NewPayload(header Header, data []byte) *Payload {
return &Payload{
Header: header,
Data: data,
}
}
// Parse is a wrapper for simplified unmarshaling in a byte stream using the marshalUtil package.
func Parse(marshalUtil *marshalutil.MarshalUtil) (*Payload, error) {
// PayloadFromMarshalUtil is a wrapper for simplified unmarshaling in a byte stream using the marshalUtil package.
func PayloadFromMarshalUtil(marshalUtil *marshalutil.MarshalUtil) (*Payload, error) {
payload, err := marshalUtil.Parse(func(data []byte) (interface{}, int, error) { return FromBytes(data) })
if err != nil {
err = fmt.Errorf("failed to parse drng payload: %w", err)
......@@ -62,13 +61,13 @@ func FromBytes(bytes []byte) (result *Payload, consumedBytes int, err error) {
}
// parse header
if result.Header, err = header.Parse(marshalUtil); err != nil {
if result.Header, err = HeaderFromMarshalUtil(marshalUtil); err != nil {
err = fmt.Errorf("failed to parse header of drng payload: %w", err)
return
}
// parse data
if result.Data, err = marshalUtil.ReadBytes(int(len - header.Length)); err != nil {
if result.Data, err = marshalUtil.ReadBytes(int(len - HeaderLength)); err != nil {
err = fmt.Errorf("failed to parse data of drng payload: %w", err)
return
}
......@@ -83,64 +82,64 @@ func FromBytes(bytes []byte) (result *Payload, consumedBytes int, err error) {
}
// Bytes returns the drng payload bytes.
func (payload *Payload) Bytes() (bytes []byte) {
func (p *Payload) Bytes() (bytes []byte) {
// acquire lock for reading bytes
payload.bytesMutex.RLock()
p.bytesMutex.RLock()
// return if bytes have been determined already
if bytes = payload.bytes; bytes != nil {
payload.bytesMutex.RUnlock()
if bytes = p.bytes; bytes != nil {
p.bytesMutex.RUnlock()
return
}
// switch to write lock
payload.bytesMutex.RUnlock()
payload.bytesMutex.Lock()
defer payload.bytesMutex.Unlock()
p.bytesMutex.RUnlock()
p.bytesMutex.Lock()
defer p.bytesMutex.Unlock()
// return if bytes have been determined in the mean time
if bytes = payload.bytes; bytes != nil {
if bytes = p.bytes; bytes != nil {
return
}
// initialize helper
marshalUtil := marshalutil.New()
// marshal the payload specific information
marshalUtil.WriteUint32(uint32(len(payload.Data) + header.Length))
marshalUtil.WriteUint32(Type)
marshalUtil.WriteBytes(payload.Header.Bytes())
marshalUtil.WriteBytes(payload.Data[:])
marshalUtil.WriteUint32(uint32(len(p.Data) + HeaderLength))
marshalUtil.WriteUint32(PayloadType)
marshalUtil.WriteBytes(p.Header.Bytes())
marshalUtil.WriteBytes(p.Data[:])
bytes = marshalUtil.Bytes()
return
}
func (payload *Payload) String() string {
func (p *Payload) String() string {
return stringify.Struct("Payload",
stringify.StructField("type", uint64(payload.Header.PayloadType)),
stringify.StructField("instance", uint64(payload.Header.InstanceID)),
stringify.StructField("data", payload.Data),
stringify.StructField("type", uint64(p.Header.PayloadType)),
stringify.StructField("instance", uint64(p.Header.InstanceID)),
stringify.StructField("data", p.Data),
)
}
// region Payload implementation ///////////////////////////////////////////////////////////////////////////////////////
// Type defines the type of the drng payload.
var Type = tangle.PayloadType(111)
// PayloadType defines the type of the drng payload.
var PayloadType = tangle.PayloadType(111)
// Type returns the type of the drng payload.
func (payload *Payload) Type() tangle.PayloadType {
return Type
func (p *Payload) Type() tangle.PayloadType {
return PayloadType
}
// Marshal marshals the drng payload into bytes.
func (payload *Payload) Marshal() (bytes []byte, err error) {
return payload.Bytes(), nil
func (p *Payload) Marshal() (bytes []byte, err error) {
return p.Bytes(), nil
}
func init() {
tangle.RegisterPayloadType(Type, ObjectName, func(data []byte) (payload tangle.Payload, err error) {
tangle.RegisterPayloadType(PayloadType, ObjectName, func(data []byte) (payload tangle.Payload, err error) {
payload, _, err = FromBytes(data)
return
......
package payload
package drng
import (
"testing"
"github.com/iotaledger/goshimmer/packages/binary/drng/payload/header"
"github.com/iotaledger/hive.go/marshalutil"
"github.com/stretchr/testify/require"
)
func dummyPayload() *Payload {
header := header.New(header.TypeCollectiveBeacon, 0)
header := NewHeader(TypeCollectiveBeacon, 0)
data := []byte("test")
return New(header, data)
return NewPayload(header, data)
}
func TestParse(t *testing.T) {
func TestPayloadFromMarshalUtil(t *testing.T) {
payload := dummyPayload()
bytes := payload.Bytes()
marshalUtil := marshalutil.New(bytes)
parsedPayload, err := Parse(marshalUtil)
parsedPayload, err := PayloadFromMarshalUtil(marshalUtil)
require.NoError(t, err)
require.Equal(t, payload.Header.PayloadType, parsedPayload.Header.PayloadType)
......
package state
package drng
import (
"testing"
......@@ -26,7 +26,7 @@ func dummyCommittee() *Committee {
func TestState(t *testing.T) {
// constructor
stateTest := New(SetCommittee(dummyCommittee()), SetRandomness(dummyRandomness()))
stateTest := NewState(SetCommittee(dummyCommittee()), SetRandomness(dummyRandomness()))
require.Equal(t, *dummyRandomness(), stateTest.Randomness())
require.Equal(t, *dummyCommittee(), stateTest.Committee())
......@@ -45,7 +45,7 @@ func TestFloat64(t *testing.T) {
max := []byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}
r := &Randomness{1, max, time.Now()}
stateTest := New(SetRandomness(r))
stateTest := NewState(SetRandomness(r))
require.Equal(t, 0.9999999999999999, stateTest.Randomness().Float64())
}
......@@ -4,7 +4,7 @@ import (
"encoding/hex"
"time"
"github.com/iotaledger/goshimmer/packages/binary/drng/state"
drngpkg "github.com/iotaledger/goshimmer/packages/drng"
"github.com/iotaledger/goshimmer/packages/shutdown"
"github.com/iotaledger/goshimmer/plugins/drng"
"github.com/iotaledger/hive.go/daemon"
......@@ -26,7 +26,7 @@ type drngMsg struct {
func configureDrngLiveFeed() {
drngLiveFeedWorkerPool = workerpool.New(func(task workerpool.Task) {
newRandomness := task.Param(0).(state.Randomness)
newRandomness := task.Param(0).(drngpkg.Randomness)
broadcastWsMessage(&wsmsg{MsgTypeDrng, &drngMsg{
Instance: drng.Instance().State.Committee().InstanceID,
......@@ -44,7 +44,7 @@ func runDrngLiveFeed() {
newMsgRateLimiter := time.NewTicker(time.Second / 10)
defer newMsgRateLimiter.Stop()
notifyNewRandomness := events.NewClosure(func(message state.Randomness) {
notifyNewRandomness := events.NewClosure(func(message drngpkg.Randomness) {
select {
case <-newMsgRateLimiter.C:
drngLiveFeedWorkerPool.TrySubmit(message)
......
......@@ -5,9 +5,7 @@ import (
"github.com/iotaledger/goshimmer/dapps/valuetransfers/packages/address"
"github.com/iotaledger/goshimmer/dapps/valuetransfers/packages/balance"
valuepayload "github.com/iotaledger/goshimmer/dapps/valuetransfers/packages/payload"
drngpayload "github.com/iotaledger/goshimmer/packages/binary/drng/payload"
drngheader "github.com/iotaledger/goshimmer/packages/binary/drng/payload/header"
cb "github.com/iotaledger/goshimmer/packages/binary/drng/subtypes/collectivebeacon/payload"
"github.com/iotaledger/goshimmer/packages/drng"
"github.com/iotaledger/goshimmer/packages/tangle"
syncbeaconpayload "github.com/iotaledger/goshimmer/plugins/syncbeacon/payload"
"github.com/iotaledger/hive.go/marshalutil"
......@@ -91,7 +89,7 @@ func ProcessPayload(p tangle.Payload) interface{} {
ContentTitle: "address",
Content: p.(*faucetpayload.Payload).Address().String(),
}
case drngpayload.Type:
case drng.PayloadType:
// drng payload
return processDrngPayload(p)
case syncbeaconpayload.Type:
......@@ -112,13 +110,13 @@ func ProcessPayload(p tangle.Payload) interface{} {
func processDrngPayload(p tangle.Payload) (dp DrngPayload) {
var subpayload interface{}
marshalUtil := marshalutil.New(p.Bytes())
drngPayload, _ := drngpayload.Parse(marshalUtil)
drngPayload, _ := drng.PayloadFromMarshalUtil(marshalUtil)
switch drngPayload.Header.PayloadType {
case drngheader.TypeCollectiveBeacon:
case drng.TypeCollectiveBeacon:
// collective beacon
marshalUtil := marshalutil.New(p.Bytes())
cbp, _ := cb.Parse(marshalUtil)
cbp, _ := drng.CollectiveBeaconPayloadFromMarshalUtil(marshalUtil)
subpayload = DrngCollectiveBeaconPayload{
Round: cbp.Round,
PrevSig: cbp.PrevSignature,
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment