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

:sparkles: adds dispatcher logic for collective beacons

parent 7936d873
No related branches found
No related tags found
No related merge requests found
...@@ -2,13 +2,20 @@ package drng ...@@ -2,13 +2,20 @@ package drng
import ( import (
"github.com/iotaledger/goshimmer/packages/binary/drng/payload/header" "github.com/iotaledger/goshimmer/packages/binary/drng/payload/header"
"github.com/iotaledger/goshimmer/packages/binary/drng/subtypes/collectiveBeacon"
"github.com/iotaledger/goshimmer/packages/binary/tangle/model/transaction" "github.com/iotaledger/goshimmer/packages/binary/tangle/model/transaction"
) )
func Dispatch(subtype header.Type, tx *transaction.Transaction) { func (drng *Instance) Dispatch(subtype header.Type, tx *transaction.Transaction) {
switch subtype { switch subtype {
case header.CollectiveBeaconType(): case header.CollectiveBeaconType():
//do stuff // process collectiveBeacon
if err := collectiveBeacon.ProcessTransaction(drng.State, drng.Events.CollectiveBeacon, tx); err != nil {
return
}
// trigger RandomnessEvent
drng.Events.Randomness.Trigger(drng.State.Randomness())
default: default:
//do other stuff //do other stuff
} }
......
...@@ -2,16 +2,16 @@ package drng ...@@ -2,16 +2,16 @@ package drng
import ( import (
"github.com/iotaledger/goshimmer/packages/binary/drng/state" "github.com/iotaledger/goshimmer/packages/binary/drng/state"
"github.com/iotaledger/hive.go/events"
) )
type Instance struct { type Instance struct {
State *state.State State *state.State
Events *events.Event Events *Event
} }
func New() *Instance { func New(setters ...state.Option) *Instance {
return &Instance{ return &Instance{
State: state.New(), State: state.New(setters...),
Events: NewEvent(),
} }
} }
package drng package drng
import ( 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" "github.com/iotaledger/hive.go/events"
) )
var Events = struct { type Event struct {
NewRandomness *events.Event CollectiveBeacon cbEvents.CollectiveBeacon
}{ Randomness *events.Event
NewRandomness: events.NewEvent(transactionCaller),
} }
func transactionCaller(handler interface{}, params ...interface{}) { func NewEvent() *Event {
//handler.(func(*value_transaction.ValueTransaction))(params[0].(*value_transaction.ValueTransaction)) return &Event{
CollectiveBeacon: cbEvents.NewCollectiveBeaconEvent(),
Randomness: events.NewEvent(randomnessReceived),
}
}
func randomnessReceived(handler interface{}, params ...interface{}) {
handler.(func(*state.Randomness))(params[0].(*state.Randomness))
} }
...@@ -5,17 +5,17 @@ type Options struct { ...@@ -5,17 +5,17 @@ type Options struct {
Randomness *Randomness Randomness *Randomness
} }
type option func(*Options) type Option func(*Options)
// SetCommittee sets the initial committee // SetCommittee sets the initial committee
func SetCommittee(c *Committee) option { func SetCommittee(c *Committee) Option {
return func(args *Options) { return func(args *Options) {
args.Committee = c args.Committee = c
} }
} }
// SetRandomness sets the initial randomness // SetRandomness sets the initial randomness
func SetRandomness(r *Randomness) option { func SetRandomness(r *Randomness) Option {
return func(args *Options) { return func(args *Options) {
args.Randomness = r args.Randomness = r
} }
......
...@@ -27,7 +27,7 @@ type State struct { ...@@ -27,7 +27,7 @@ type State struct {
mutex sync.RWMutex mutex sync.RWMutex
} }
func New(setters ...option) *State { func New(setters ...Option) *State {
args := &Options{} args := &Options{}
for _, setter := range setters { for _, setter := range setters {
......
...@@ -6,23 +6,99 @@ import ( ...@@ -6,23 +6,99 @@ import (
"github.com/drand/drand/beacon" "github.com/drand/drand/beacon"
"github.com/drand/drand/key" "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/goshimmer/packages/binary/drng/subtypes/collectiveBeacon/payload" "github.com/iotaledger/goshimmer/packages/binary/drng/subtypes/collectiveBeacon/payload"
"github.com/iotaledger/goshimmer/packages/binary/marshalutil"
"github.com/iotaledger/goshimmer/packages/binary/signature/ed25119"
"github.com/iotaledger/goshimmer/packages/binary/tangle/model/transaction"
) )
// VerifyCollectiveBeacon checks the current signature against the distributed public key // ProcessTransaction performs the following tasks:
func VerifyCollectiveBeacon(data *payload.Payload) error { // 1 - parse as CollectiveBeaconType
// 2 - trigger CollectiveBeaconEvent
// 3 - verify that we have a valid random
// 4 - update drng state
func ProcessTransaction(drng *state.State, event events.CollectiveBeacon, tx *transaction.Transaction) error {
// 1 - parse as CollectiveBeaconType
marshalUtil := marshalutil.New(tx.GetPayload().Bytes())
parsedPayload, err := payload.Parse(marshalUtil)
if err != nil {
return err
}
// 2 - trigger CollectiveBeaconEvent
cbEvent := &events.CollectiveBeaconEvent{
IssuerPublicKey: tx.IssuerPublicKey(),
Timestamp: tx.IssuingTime(),
InstanceID: parsedPayload.Instance(),
Round: parsedPayload.Round(),
PrevSignature: parsedPayload.PrevSignature(),
Signature: parsedPayload.Signature(),
Dpk: parsedPayload.DistributedPK(),
}
event.Trigger(cbEvent)
// 3 - verify that we have a valid random
if err := VerifyCollectiveBeacon(drng, cbEvent); err != nil {
//TODO: handle error
return err
}
// 4 - update drng state
randomness, err := GetRandomness(cbEvent.Signature)
if err != nil {
//TODO: handle error
return err
}
newRandomness := &state.Randomness{
Round: cbEvent.Round,
Randomness: randomness,
Timestamp: cbEvent.Timestamp,
}
drng.SetRandomness(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 {
if err := verifyIssuer(state, data.IssuerPublicKey); err != nil {
return err
}
if err := verifySignature(data); err != nil {
return err
}
return nil
}
// verifyIssuer checks the given issuer is a member of the committee
func verifyIssuer(state *state.State, issuer ed25119.PublicKey) error {
for _, member := range state.Committee().Identities {
if member == issuer {
return nil
}
}
return errors.New("Invalid Issuer")
}
// verifySignature checks the current signature against the distributed public key
func verifySignature(data *events.CollectiveBeaconEvent) error {
if data == nil { if data == nil {
return errors.New("nil data") return errors.New("nil data")
} }
dpk := key.KeyGroup.Point() dpk := key.KeyGroup.Point()
if err := dpk.UnmarshalBinary(data.DistributedPK()); err != nil { if err := dpk.UnmarshalBinary(data.Dpk); err != nil {
return err return err
} }
msg := beacon.Message(data.PrevSignature(), data.Round()) msg := beacon.Message(data.PrevSignature, data.Round)
if err := key.Scheme.VerifyRecovered(dpk, msg, data.Signature()); err != nil { if err := key.Scheme.VerifyRecovered(dpk, msg, data.Signature); err != nil {
return err return err
} }
......
...@@ -4,12 +4,12 @@ import ( ...@@ -4,12 +4,12 @@ import (
"encoding/hex" "encoding/hex"
"testing" "testing"
"github.com/iotaledger/goshimmer/packages/binary/drng/subtypes/collectiveBeacon/payload" "github.com/iotaledger/goshimmer/packages/binary/drng/subtypes/collectiveBeacon/events"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
var ( var (
payloadTest *payload.Payload eventTest *events.CollectiveBeaconEvent
prevSignatureTest []byte prevSignatureTest []byte
signatureTest []byte signatureTest []byte
dpkTest []byte dpkTest []byte
...@@ -19,18 +19,24 @@ func init() { ...@@ -19,18 +19,24 @@ func init() {
prevSignatureTest, _ = hex.DecodeString("ae9ba6d1445bffea8e66cb7d28fe5924e0a8d31b11b62a8710204e56e1ba84bc3694a3033e5793fcee6e75e956e5da3016cd0e22aa46fa419cd06343a7ff9d1e9c5c08f660f0bdec099e97ef99f470bb8c607ce9667a165e9caa474710f62ffd") prevSignatureTest, _ = hex.DecodeString("ae9ba6d1445bffea8e66cb7d28fe5924e0a8d31b11b62a8710204e56e1ba84bc3694a3033e5793fcee6e75e956e5da3016cd0e22aa46fa419cd06343a7ff9d1e9c5c08f660f0bdec099e97ef99f470bb8c607ce9667a165e9caa474710f62ffd")
signatureTest, _ = hex.DecodeString("8dee56fae60dcad960f7176d0813d5415b930cf6e20c299ec2c2dfc5f2ad4903916fd462ba1abf5c32a5bfd94dcc8eba062d011a548d99df7fa1e3bbbc9a0455663d60f6ccc736c1d5b6de727dbe4427e21fb660925518be386265913f447c94") signatureTest, _ = hex.DecodeString("8dee56fae60dcad960f7176d0813d5415b930cf6e20c299ec2c2dfc5f2ad4903916fd462ba1abf5c32a5bfd94dcc8eba062d011a548d99df7fa1e3bbbc9a0455663d60f6ccc736c1d5b6de727dbe4427e21fb660925518be386265913f447c94")
dpkTest, _ = hex.DecodeString("a02fcd15edd52c8e134027491a43b597505b466d1679e88f70f927e57c45a93ae0765ff02fc2d015e3a02fd8748e2103") dpkTest, _ = hex.DecodeString("a02fcd15edd52c8e134027491a43b597505b466d1679e88f70f927e57c45a93ae0765ff02fc2d015e3a02fd8748e2103")
payloadTest = payload.New(1, 1, prevSignatureTest, signatureTest, dpkTest) eventTest = &events.CollectiveBeaconEvent{
InstanceID: 1,
Round: 1,
PrevSignature: prevSignatureTest,
Signature: signatureTest,
Dpk: dpkTest,
}
} }
func TestVerifyCollectiveBeacon(t *testing.T) { func TestVerifySignature(t *testing.T) {
//payload := dkgShares(t, 5, 3) //payload := dkgShares(t, 5, 3)
err := VerifyCollectiveBeacon(payloadTest) err := verifySignature(eventTest)
require.NoError(t, err) require.NoError(t, err)
} }
func TestGetRandomness(t *testing.T) { func TestGetRandomness(t *testing.T) {
//payload := dkgShares(t, 5, 3) //payload := dkgShares(t, 5, 3)
_, err := GetRandomness(payloadTest.Signature()) _, err := GetRandomness(eventTest.Signature)
require.NoError(t, err) require.NoError(t, err)
} }
......
package events
import (
"time"
"github.com/iotaledger/goshimmer/packages/binary/signature/ed25119"
"github.com/iotaledger/hive.go/events"
)
type CollectiveBeacon = *events.Event
func NewCollectiveBeaconEvent() *events.Event {
return events.NewEvent(collectiveBeaconReceived)
}
type CollectiveBeaconEvent struct {
IssuerPublicKey ed25119.PublicKey // public key of the issuer
Timestamp time.Time // timestamp when the beacon was issued
InstanceID uint32 // instanceID of the beacon
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
}
func collectiveBeaconReceived(handler interface{}, params ...interface{}) {
handler.(func(*CollectiveBeaconEvent))(params[0].(*CollectiveBeaconEvent))
}
package events
import (
"testing"
"time"
"github.com/iotaledger/hive.go/events"
"github.com/stretchr/testify/require"
)
func TestCollectiveBeaconEvent(t *testing.T) {
var cbReceived *CollectiveBeaconEvent
eventTest := NewCollectiveBeaconEvent()
eventTest.Attach(events.NewClosure(func(cb *CollectiveBeaconEvent) {
cbReceived = cb
}))
cbTriggered := &CollectiveBeaconEvent{
Timestamp: time.Now(),
}
eventTest.Trigger(cbTriggered)
require.Equal(t, cbTriggered, cbReceived)
}
...@@ -163,6 +163,11 @@ func (transaction *Transaction) IssuingTime() time.Time { ...@@ -163,6 +163,11 @@ func (transaction *Transaction) IssuingTime() time.Time {
return transaction.issuingTime return transaction.issuingTime
} }
// IssuerPublicKey returns the issuer PublicKey of the transaction.
func (transaction *Transaction) IssuerPublicKey() ed25119.PublicKey {
return transaction.issuerPublicKey
}
// SequenceNumber returns the sequence number of this transaction. // SequenceNumber returns the sequence number of this transaction.
func (transaction *Transaction) SequenceNumber() uint64 { func (transaction *Transaction) SequenceNumber() uint64 {
return transaction.sequenceNumber return transaction.sequenceNumber
......
package drng
import (
"github.com/iotaledger/goshimmer/packages/binary/drng"
"github.com/iotaledger/goshimmer/packages/binary/drng/payload"
"github.com/iotaledger/goshimmer/packages/binary/marshalutil"
"github.com/iotaledger/goshimmer/packages/binary/tangle/model/transaction"
"github.com/iotaledger/goshimmer/packages/binary/tangle/model/transactionmetadata"
"github.com/iotaledger/goshimmer/plugins/tangle"
"github.com/iotaledger/hive.go/events"
"github.com/iotaledger/hive.go/node"
)
const name = "DRNG" // name of the plugin
var PLUGIN = node.NewPlugin(name, node.Enabled, configure, run)
var Instance *drng.Instance
func configure(*node.Plugin) {
Instance = drng.New()
configureEvents()
}
func run(*node.Plugin) {}
func configureEvents() {
tangle.Instance.Events.TransactionSolid.Attach(events.NewClosure(func(cachedTransaction *transaction.CachedTransaction, cachedTransactionMetadata *transactionmetadata.CachedTransactionMetadata) {
cachedTransactionMetadata.Release()
cachedTransaction.Consume(func(transaction *transaction.Transaction) {
marshalUtil := marshalutil.New(transaction.GetPayload().Bytes())
parsedPayload, err := payload.Parse(marshalUtil)
if err != nil {
return
}
Instance.Dispatch(parsedPayload.SubType(), transaction)
})
}))
}
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