add: Drand network integration with random beacon

This commit is contained in:
bahadylbekov 2020-10-23 16:35:30 +03:00
parent c49acb189f
commit 5d17d90c28
6 changed files with 901 additions and 13 deletions

30
config/drand.go Normal file
View File

@ -0,0 +1,30 @@
package config
type DrandConfig struct {
Servers []string
GossipRelays []string
ChainInfo string
}
func NewDrandConfig() *DrandConfig {
cfg := &DrandConfig{
Servers: []string{
"https://api.drand.sh",
"https://api2.drand.sh",
"https://api3.drand.sh",
"https://drand.cloudflare.com",
},
GossipRelays: []string{
"/dnsaddr/api.drand.sh/",
"/dnsaddr/api2.drand.sh/",
"/dnsaddr/api3.drand.sh/",
},
ChainInfo: `{
"public_key": "868f005eb8e6e4ca0a47c8a77ceaa5309a47978a7c71bc5cce96366b5d7a569937c529eeda66c7293784a9402801af31",
"period": 30,
"genesis_time": 1595431050,
"hash": "8990e7a9aaed2ffed73dbd7092123d6f289930540d7651336225dc172e51b2ce"
}`,
}
return cfg
}

25
go.mod
View File

@ -7,27 +7,31 @@ require (
github.com/aristanetworks/goarista v0.0.0-20200224203130-895b4c57c44d // indirect github.com/aristanetworks/goarista v0.0.0-20200224203130-895b4c57c44d // indirect
github.com/cespare/cp v1.1.1 // indirect github.com/cespare/cp v1.1.1 // indirect
github.com/deckarep/golang-set v1.7.1 // indirect github.com/deckarep/golang-set v1.7.1 // indirect
github.com/drand/drand v1.2.1
github.com/drand/kyber v1.1.5
github.com/elastic/gosigar v0.10.5 // indirect github.com/elastic/gosigar v0.10.5 // indirect
github.com/ethereum/go-ethereum v1.9.5 github.com/ethereum/go-ethereum v1.9.5
github.com/filecoin-project/go-state-types v0.0.0-20201021025442-0ac4de847f4f
github.com/filecoin-project/lotus v1.1.0
github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 // indirect github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 // indirect
github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 // indirect github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 // indirect
github.com/go-kit/kit v0.10.0 // indirect github.com/go-kit/kit v0.10.0
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e // indirect github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e // indirect
github.com/golang/protobuf v1.4.2 // indirect github.com/golang/protobuf v1.4.2 // indirect
github.com/google/uuid v1.1.1 github.com/google/uuid v1.1.1
github.com/gopherjs/gopherjs v0.0.0-20190812055157-5d271430af9f // indirect github.com/gopherjs/gopherjs v0.0.0-20190812055157-5d271430af9f // indirect
github.com/ipfs/go-log v1.0.4
github.com/ipfs/go-log/v2 v2.1.2-0.20200626104915-0016c0b4b3e4 github.com/ipfs/go-log/v2 v2.1.2-0.20200626104915-0016c0b4b3e4
github.com/karalabe/usb v0.0.0-20191104083709-911d15fe12a9 // indirect github.com/karalabe/usb v0.0.0-20191104083709-911d15fe12a9 // indirect
github.com/libp2p/go-libp2p v0.10.2 github.com/libp2p/go-libp2p v0.11.0
github.com/libp2p/go-libp2p-core v0.6.1 github.com/libp2p/go-libp2p-core v0.6.1
github.com/libp2p/go-libp2p-discovery v0.5.0 github.com/libp2p/go-libp2p-discovery v0.5.0
github.com/libp2p/go-libp2p-kad-dht v0.8.3 github.com/libp2p/go-libp2p-kad-dht v0.8.3
github.com/libp2p/go-libp2p-peerstore v0.2.6 github.com/libp2p/go-libp2p-peerstore v0.2.6
github.com/libp2p/go-libp2p-pubsub v0.3.3 github.com/libp2p/go-libp2p-pubsub v0.3.6
github.com/mattn/go-colorable v0.1.4 // indirect github.com/multiformats/go-multiaddr v0.3.1
github.com/mattn/go-isatty v0.0.12 // indirect
github.com/multiformats/go-multiaddr v0.2.2
github.com/olekukonko/tablewriter v0.0.4 // indirect github.com/olekukonko/tablewriter v0.0.4 // indirect
github.com/raulk/clock v1.1.0
github.com/rjeczalik/notify v0.9.2 // indirect github.com/rjeczalik/notify v0.9.2 // indirect
github.com/rs/cors v1.7.0 // indirect github.com/rs/cors v1.7.0 // indirect
github.com/sirupsen/logrus v1.6.0 github.com/sirupsen/logrus v1.6.0
@ -36,18 +40,13 @@ require (
github.com/status-im/keycard-go v0.0.0-20200402102358-957c09536969 // indirect github.com/status-im/keycard-go v0.0.0-20200402102358-957c09536969 // indirect
github.com/steakknife/bloomfilter v0.0.0-20180922174646-6819c0d2a570 // indirect github.com/steakknife/bloomfilter v0.0.0-20180922174646-6819c0d2a570 // indirect
github.com/steakknife/hamming v0.0.0-20180906055917-c99c65617cd3 // indirect github.com/steakknife/hamming v0.0.0-20180906055917-c99c65617cd3 // indirect
github.com/stretchr/testify v1.6.1
github.com/tyler-smith/go-bip39 v1.0.2 // indirect github.com/tyler-smith/go-bip39 v1.0.2 // indirect
github.com/wsddn/go-ecdh v0.0.0-20161211032359-48726bab9208 // indirect github.com/wsddn/go-ecdh v0.0.0-20161211032359-48726bab9208 // indirect
golang.org/x/crypto v0.0.0-20200604202706-70a84ac30bf9 // indirect
golang.org/x/lint v0.0.0-20200302205851-738671d3881b // indirect golang.org/x/lint v0.0.0-20200302205851-738671d3881b // indirect
golang.org/x/net v0.0.0-20200602114024-627f9648deb9 // indirect golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1
golang.org/x/sys v0.0.0-20200602225109-6fdc65e7d980 // indirect
golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4 // indirect
google.golang.org/grpc v1.29.1 // indirect
google.golang.org/protobuf v1.24.0 // indirect
gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce // indirect gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce // indirect
gopkg.in/olebedev/go-duktape.v3 v3.0.0-20200619000410-60c24ae608a6 // indirect gopkg.in/olebedev/go-duktape.v3 v3.0.0-20200619000410-60c24ae608a6 // indirect
gopkg.in/urfave/cli.v1 v1.20.0 // indirect gopkg.in/urfave/cli.v1 v1.20.0 // indirect
gopkg.in/yaml.v2 v2.2.8 // indirect
honnef.co/go/tools v0.0.1-2020.1.3 // indirect honnef.co/go/tools v0.0.1-2020.1.3 // indirect
) )

674
go.sum

File diff suppressed because it is too large Load Diff

5
lib/clock.go Normal file
View File

@ -0,0 +1,5 @@
package lib
import "github.com/raulk/clock"
var Clock = clock.New()

157
lib/drand/drand.go Normal file
View File

@ -0,0 +1,157 @@
package drand
import (
"bytes"
"context"
"fmt"
"sync"
"time"
"github.com/drand/drand/chain"
"github.com/drand/drand/client"
httpClient "github.com/drand/drand/client/http"
libp2pClient "github.com/drand/drand/lp2p/client"
"github.com/drand/kyber"
"github.com/sirupsen/logrus"
pubsub "github.com/libp2p/go-libp2p-pubsub"
"github.com/Secured-Finance/dione/config"
"github.com/Secured-Finance/dione/lib"
)
type DrandRes struct {
// PreviousSig is the previous signature generated
PreviousSig []byte
// Round is the round number this beacon is tied to
Round uint64
// Signature is the BLS deterministic signature over Round || PreviousRand
Signature []byte
// Randomness for specific round generated by Drand
Randomness []byte
}
type Beacon struct {
DrandResponse DrandRes
Error error
}
type DrandBeacon struct {
DrandClient client.Client
PublicKey kyber.Point
Interval time.Duration
drandGenesisTime uint64
cacheLock sync.Mutex
localCache map[uint64]DrandRes
}
func NewDrandBeacon(ps *pubsub.PubSub) (*DrandBeacon, error) {
cfg := config.NewDrandConfig()
drandChain, err := chain.InfoFromJSON(bytes.NewReader([]byte(cfg.ChainInfo)))
if err != nil {
return nil, fmt.Errorf("unable to unmarshal drand chain info: %w", err)
}
var clients []client.Client
for _, url := range cfg.Servers {
client, err := httpClient.NewWithInfo(url, drandChain, nil)
if err != nil {
return nil, fmt.Errorf("could not create http drand client: %w", err)
}
clients = append(clients, client)
}
opts := []client.Option{
client.WithChainInfo(drandChain),
client.WithCacheSize(1024),
client.WithAutoWatch(),
}
if ps != nil {
opts = append(opts, libp2pClient.WithPubsub(ps))
} else {
logrus.Info("Initiated drand with PubSub")
}
drandClient, err := client.Wrap(clients, opts...)
if err != nil {
return nil, fmt.Errorf("Couldn't create Drand clients")
}
db := &DrandBeacon{
DrandClient: drandClient,
localCache: make(map[uint64]DrandRes),
}
db.PublicKey = drandChain.PublicKey
db.Interval = drandChain.Period
db.drandGenesisTime = uint64(drandChain.GenesisTime)
return db, nil
}
func (db *DrandBeacon) Entry(ctx context.Context, round uint64) <-chan Beacon {
out := make(chan Beacon, 1)
if round != 0 {
res := db.getCachedValue(round)
if res != nil {
out <- Beacon{DrandResponse: *res}
close(out)
return out
}
}
go func() {
start := lib.Clock.Now()
logrus.Info("start fetching randomness", "round", round)
resp, err := db.DrandClient.Get(ctx, round)
var res Beacon
if err != nil {
res.Error = fmt.Errorf("drand failed Get request: %w", err)
} else {
res.DrandResponse.Round = resp.Round()
res.DrandResponse.Signature = resp.Signature()
}
logrus.Info("done fetching randomness", "round", round, "took", lib.Clock.Since(start))
out <- res
close(out)
}()
return out
}
func (db *DrandBeacon) cacheValue(res DrandRes) {
db.cacheLock.Lock()
defer db.cacheLock.Unlock()
db.localCache[res.Round] = res
}
func (db *DrandBeacon) getCachedValue(round uint64) *DrandRes {
db.cacheLock.Lock()
defer db.cacheLock.Unlock()
v, ok := db.localCache[round]
if !ok {
return nil
}
return &v
}
func (db *DrandBeacon) VerifyEntry(curr DrandRes, prev DrandRes) error {
if prev.Round == 0 {
return nil
}
if be := db.getCachedValue(curr.Round); be != nil {
return nil
}
b := &chain.Beacon{
PreviousSig: prev.PreviousSig,
Round: curr.Round,
Signature: curr.Signature,
}
err := chain.VerifyBeacon(db.PublicKey, b)
if err == nil {
db.cacheValue(curr)
}
return err
}

23
lib/drand/drand_test.go Normal file
View File

@ -0,0 +1,23 @@
package drand
import (
"context"
"encoding/hex"
"testing"
"github.com/Secured-Finance/dione/config"
drandClient "github.com/drand/drand/client/http"
"github.com/stretchr/testify/assert"
)
func TestPrintGroupInfo(t *testing.T) {
cfg := config.NewDrandConfig()
ctx := context.Background()
drandServer := cfg.Servers[0]
client, err := drandClient.New(drandServer, nil, nil)
assert.NoError(t, err)
drandResult, err := client.Get(ctx, 266966)
assert.NoError(t, err)
stringSha256 := hex.EncodeToString(drandResult.Randomness())
assert.Equal(t, stringSha256, "cb67e13477cad0e54540980a3b621dfd9c5fcd7c92ed42626289a1de6f25c3d1")
}