Add Type field to DioneTask, rename rpcclient to ethclient, rewrite whole signing system in Dione, add some comments to consensus process (w/ mining system)
This commit is contained in:
parent
6636a279e7
commit
0b37896af9
@ -15,9 +15,9 @@ type Response struct {
|
||||
Err error
|
||||
}
|
||||
|
||||
type Schedule []BeaconPoint
|
||||
type Queue []BeaconPoint
|
||||
|
||||
func (bs Schedule) BeaconForEpoch(e types.TaskEpoch) RandomBeacon {
|
||||
func (bs Queue) BeaconForEpoch(e types.TaskEpoch) RandomBeacon {
|
||||
for i := len(bs) - 1; i >= 0; i-- {
|
||||
bp := bs[i]
|
||||
if e >= bp.Start {
|
||||
@ -42,10 +42,10 @@ type RandomBeacon interface {
|
||||
MaxBeaconRoundForEpoch(types.TaskEpoch) uint64
|
||||
}
|
||||
|
||||
func ValidateTaskValues(bSchedule Schedule, t *types.DioneTask, parentEpoch types.TaskEpoch, prevEntry types.BeaconEntry) error {
|
||||
func ValidateTaskValues(bQueue Queue, t *types.DioneTask, parentEpoch types.TaskEpoch, prevEntry types.BeaconEntry) error {
|
||||
{
|
||||
parentBeacon := bSchedule.BeaconForEpoch(parentEpoch)
|
||||
currBeacon := bSchedule.BeaconForEpoch(t.Epoch)
|
||||
parentBeacon := bQueue.BeaconForEpoch(parentEpoch)
|
||||
currBeacon := bQueue.BeaconForEpoch(t.Epoch)
|
||||
if parentBeacon != currBeacon {
|
||||
if len(t.BeaconEntries) != 2 {
|
||||
return fmt.Errorf("expected two beacon entries at beacon fork, got %d", len(t.BeaconEntries))
|
||||
@ -60,7 +60,7 @@ func ValidateTaskValues(bSchedule Schedule, t *types.DioneTask, parentEpoch type
|
||||
}
|
||||
|
||||
// TODO: fork logic
|
||||
b := bSchedule.BeaconForEpoch(t.Epoch)
|
||||
b := bQueue.BeaconForEpoch(t.Epoch)
|
||||
maxRound := b.MaxBeaconRoundForEpoch(t.Epoch)
|
||||
if maxRound == prevEntry.Round {
|
||||
if len(t.BeaconEntries) != 0 {
|
||||
@ -88,7 +88,7 @@ func ValidateTaskValues(bSchedule Schedule, t *types.DioneTask, parentEpoch type
|
||||
return nil
|
||||
}
|
||||
|
||||
func BeaconEntriesForTask(ctx context.Context, bSchedule Schedule, epoch types.TaskEpoch, parentEpoch types.TaskEpoch, prev types.BeaconEntry) ([]types.BeaconEntry, error) {
|
||||
func BeaconEntriesForTask(ctx context.Context, bSchedule Queue, epoch types.TaskEpoch, parentEpoch types.TaskEpoch, prev types.BeaconEntry) ([]types.BeaconEntry, error) {
|
||||
{
|
||||
parentBeacon := bSchedule.BeaconForEpoch(parentEpoch)
|
||||
currBeacon := bSchedule.BeaconForEpoch(epoch)
|
||||
|
@ -50,6 +50,8 @@ func (pcm *PBFTConsensusManager) NewTestConsensus(data string, consensusID strin
|
||||
cData.onConsensusFinishCallback = onConsensusFinishCallback
|
||||
pcm.Consensuses[consensusID] = cData
|
||||
|
||||
// here we will create DioneTask
|
||||
|
||||
msg := models.Message{}
|
||||
msg.Type = "prepared"
|
||||
msg.Payload = make(map[string]interface{})
|
||||
@ -71,16 +73,19 @@ func (pcm *PBFTConsensusManager) handlePreparedMessage(message *models.Message)
|
||||
logrus.Debug("received prepared msg")
|
||||
data := pcm.Consensuses[consensusID]
|
||||
|
||||
// validate payload data
|
||||
if data.test {
|
||||
rData := message.Payload["data"].(string)
|
||||
if rData != testValidData {
|
||||
logrus.Error("Incorrect data was received! Ignoring this message, because it was sent from fault node!")
|
||||
return
|
||||
}
|
||||
} else {
|
||||
// TODO
|
||||
}
|
||||
//// validate payload data
|
||||
//if data.test {
|
||||
// rData := message.Payload["data"].(string)
|
||||
// if rData != testValidData {
|
||||
// logrus.Error("Incorrect data was received! Ignoring this message, because it was sent from fault node!")
|
||||
// return
|
||||
// }
|
||||
//} else {
|
||||
// // TODO
|
||||
//}
|
||||
|
||||
// here we can validate miner which produced this task, is he winner, and so on
|
||||
// we must to reconstruct transaction here for validating task itself
|
||||
|
||||
data.mutex.Lock()
|
||||
data.preparedCount++
|
||||
@ -103,7 +108,7 @@ func (pcm *PBFTConsensusManager) handlePreparedMessage(message *models.Message)
|
||||
|
||||
func (pcm *PBFTConsensusManager) handleCommitMessage(message *models.Message) {
|
||||
// TODO add check on view of the message
|
||||
// TODO add validation of data to this stage
|
||||
// TODO add validation of data by hash to this stage
|
||||
consensusID := message.Payload["consensusID"].(string)
|
||||
if _, ok := pcm.Consensuses[consensusID]; !ok {
|
||||
logrus.Warn("Unknown consensus ID: " + consensusID)
|
||||
|
@ -1,43 +1,39 @@
|
||||
package consensus
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/libp2p/go-libp2p-core/peer"
|
||||
|
||||
"github.com/Secured-Finance/dione/types"
|
||||
"github.com/filecoin-project/go-address"
|
||||
"github.com/filecoin-project/go-state-types/crypto"
|
||||
"github.com/filecoin-project/lotus/lib/sigs"
|
||||
"go.opencensus.io/trace"
|
||||
"golang.org/x/xerrors"
|
||||
)
|
||||
|
||||
type SignFunc func(context.Context, address.Address, []byte) (*crypto.Signature, error)
|
||||
type SignFunc func(context.Context, peer.ID, []byte) (*types.Signature, error)
|
||||
|
||||
func ComputeVRF(ctx context.Context, sign SignFunc, worker address.Address, sigInput []byte) ([]byte, error) {
|
||||
func ComputeVRF(ctx context.Context, sign SignFunc, worker peer.ID, sigInput []byte) ([]byte, error) {
|
||||
sig, err := sign(ctx, worker, sigInput)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if sig.Type != crypto.SigTypeBLS {
|
||||
return nil, fmt.Errorf("miner worker address was not a BLS key")
|
||||
if sig.Type != types.SigTypeEd25519 {
|
||||
return nil, fmt.Errorf("miner worker address was not a Ed25519 key")
|
||||
}
|
||||
|
||||
return sig.Data, nil
|
||||
}
|
||||
|
||||
func VerifyVRF(ctx context.Context, worker address.Address, vrfBase, vrfproof []byte) error {
|
||||
_, span := trace.StartSpan(ctx, "VerifyVRF")
|
||||
defer span.End()
|
||||
|
||||
sig := &crypto.Signature{
|
||||
Type: crypto.SigTypeBLS,
|
||||
Data: vrfproof,
|
||||
func VerifyVRF(ctx context.Context, worker peer.ID, vrfBase, vrfproof []byte) error {
|
||||
pKey, err := worker.ExtractPublicKey()
|
||||
if err != nil {
|
||||
return xerrors.Errorf("failed to extract public key from worker address: %w", err)
|
||||
}
|
||||
|
||||
if err := sigs.Verify(sig, worker, vrfBase); err != nil {
|
||||
valid, err := pKey.Verify(vrfBase, vrfproof)
|
||||
if err != nil || !valid {
|
||||
return xerrors.Errorf("vrf was invalid: %w", err)
|
||||
}
|
||||
|
||||
@ -45,14 +41,14 @@ func VerifyVRF(ctx context.Context, worker address.Address, vrfBase, vrfproof []
|
||||
}
|
||||
|
||||
func IsRoundWinner(ctx context.Context, round types.TaskEpoch,
|
||||
worker address.Address, brand types.BeaconEntry, mb *MinerBase, a MinerAPI) (*types.ElectionProof, error) {
|
||||
worker peer.ID, brand types.BeaconEntry, mb *MinerBase, a MinerAPI) (*types.ElectionProof, error) {
|
||||
|
||||
buf := new(bytes.Buffer)
|
||||
if err := worker.MarshalCBOR(buf); err != nil {
|
||||
return nil, xerrors.Errorf("failed to cbor marshal address: %w", err)
|
||||
buf, err := worker.MarshalBinary()
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("failed to marshal address: %w", err)
|
||||
}
|
||||
|
||||
electionRand, err := DrawRandomness(brand.Data, crypto.DomainSeparationTag_ElectionProofProduction, round, buf.Bytes())
|
||||
electionRand, err := DrawRandomness(brand.Data, crypto.DomainSeparationTag_ElectionProofProduction, round, buf)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("failed to draw randomness: %w", err)
|
||||
}
|
||||
|
@ -1,33 +1,33 @@
|
||||
package consensus
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"sync"
|
||||
|
||||
"github.com/libp2p/go-libp2p-core/peer"
|
||||
|
||||
"github.com/Secured-Finance/dione/types"
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/filecoin-project/go-address"
|
||||
"github.com/filecoin-project/go-state-types/crypto"
|
||||
"github.com/sirupsen/logrus"
|
||||
"golang.org/x/xerrors"
|
||||
)
|
||||
|
||||
type Miner struct {
|
||||
address address.Address
|
||||
address peer.ID
|
||||
api MinerAPI
|
||||
mutex sync.Mutex
|
||||
}
|
||||
|
||||
type MinerAPI interface {
|
||||
WalletSign(context.Context, address.Address, []byte) (*crypto.Signature, error)
|
||||
WalletSign(context.Context, peer.ID, []byte) (*types.Signature, error)
|
||||
// TODO: get miner base based on epoch;
|
||||
}
|
||||
|
||||
type MinerBase struct {
|
||||
MinerStake types.BigInt
|
||||
NetworkStake types.BigInt
|
||||
WorkerKey address.Address
|
||||
WorkerKey peer.ID
|
||||
EthWallet common.Address
|
||||
PrevBeaconEntry types.BeaconEntry
|
||||
BeaconEntries []types.BeaconEntry
|
||||
@ -36,15 +36,15 @@ type MinerBase struct {
|
||||
|
||||
type MiningBase struct {
|
||||
epoch types.TaskEpoch
|
||||
nullRounds types.TaskEpoch
|
||||
nullRounds types.TaskEpoch // currently not used
|
||||
}
|
||||
|
||||
func NewMinerBase(minerStake, networkStake types.BigInt, minerWallet address.Address,
|
||||
func NewMinerBase(minerStake, networkStake types.BigInt, minerAddress peer.ID,
|
||||
minerEthWallet common.Address, prev types.BeaconEntry, entries []types.BeaconEntry) *MinerBase {
|
||||
return &MinerBase{
|
||||
MinerStake: minerStake,
|
||||
NetworkStake: networkStake,
|
||||
WorkerKey: minerWallet,
|
||||
WorkerKey: minerAddress,
|
||||
EthWallet: minerEthWallet,
|
||||
PrevBeaconEntry: prev,
|
||||
BeaconEntries: entries,
|
||||
@ -82,21 +82,21 @@ func (m *Miner) MineTask(ctx context.Context, base *MiningBase, mb *MinerBase) (
|
||||
Miner: m.address,
|
||||
Ticket: ticket,
|
||||
ElectionProof: winner,
|
||||
BeaconEntries: mb.BeaconEntries,
|
||||
BeaconEntries: mb.BeaconEntries, // TODO decide what we need to do with multiple beacon entries
|
||||
// TODO: signature
|
||||
Epoch: round,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (m *Miner) computeTicket(ctx context.Context, brand *types.BeaconEntry, base *MiningBase, mb *MinerBase) (*types.Ticket, error) {
|
||||
buf := new(bytes.Buffer)
|
||||
if err := m.address.MarshalCBOR(buf); err != nil {
|
||||
return nil, xerrors.Errorf("failed to marshal address to cbor: %w", err)
|
||||
buf, err := m.address.MarshalBinary()
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("failed to marshal address: %w", err)
|
||||
}
|
||||
|
||||
round := base.epoch + base.nullRounds + 1
|
||||
|
||||
input, err := DrawRandomness(brand.Data, crypto.DomainSeparationTag_TicketProduction, round-types.TicketRandomnessLookback, buf.Bytes())
|
||||
input, err := DrawRandomness(brand.Data, crypto.DomainSeparationTag_TicketProduction, round-types.TicketRandomnessLookback, buf)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
package rpcclient
|
||||
package ethclient
|
||||
|
||||
import (
|
||||
"context"
|
@ -1,4 +1,4 @@
|
||||
package rpcclient
|
||||
package ethclient
|
||||
|
||||
import (
|
||||
"crypto/ecdsa"
|
31
go.mod
31
go.mod
@ -9,37 +9,43 @@ require (
|
||||
github.com/asaskevich/govalidator v0.0.0-20200907205600-7a23bdc65eef // indirect
|
||||
github.com/cespare/cp v1.1.1 // indirect
|
||||
github.com/deckarep/golang-set v1.7.1 // indirect
|
||||
github.com/dgraph-io/badger/v2 v2.2007.2 // 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/ethereum/go-ethereum v1.9.5
|
||||
github.com/filecoin-project/go-address v0.0.4
|
||||
github.com/filecoin-project/go-crypto v0.0.0-20191218222705-effae4ea9f03 // indirect
|
||||
github.com/filecoin-project/go-state-types v0.0.0-20201021025442-0ac4de847f4f
|
||||
github.com/filecoin-project/lotus v1.1.2
|
||||
github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 // indirect
|
||||
github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 // indirect
|
||||
github.com/go-kit/kit v0.10.0 // indirect
|
||||
github.com/go-ozzo/ozzo-validation v3.6.0+incompatible
|
||||
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e // indirect
|
||||
github.com/google/uuid v1.1.1 // indirect
|
||||
github.com/golang/snappy v0.0.2-0.20190904063534-ff6b7dc882cf // indirect
|
||||
github.com/google/gopacket v1.1.18 // indirect
|
||||
github.com/gopherjs/gopherjs v0.0.0-20190812055157-5d271430af9f // indirect
|
||||
github.com/ipfs/go-datastore v0.4.5 // indirect
|
||||
github.com/ipfs/go-ds-badger2 v0.1.1-0.20200708190120-187fc06f714e // indirect
|
||||
github.com/ipfs/go-ipld-cbor v0.0.5-0.20200428170625-a0bd04d3cbdf // indirect
|
||||
github.com/ipfs/go-ipld-format v0.2.0 // indirect
|
||||
github.com/ipfs/go-log/v2 v2.1.2-0.20200626104915-0016c0b4b3e4 // indirect
|
||||
github.com/jmoiron/sqlx v1.2.0
|
||||
github.com/karalabe/usb v0.0.0-20191104083709-911d15fe12a9 // indirect
|
||||
github.com/lib/pq v1.7.0 // indirect
|
||||
github.com/libp2p/go-libp2p v0.11.0
|
||||
github.com/libp2p/go-libp2p-core v0.6.1
|
||||
github.com/libp2p/go-libp2p-discovery v0.5.0 // indirect
|
||||
github.com/libp2p/go-libp2p-kad-dht v0.8.3 // indirect
|
||||
github.com/libp2p/go-libp2p-peerstore v0.2.6 // indirect
|
||||
github.com/libp2p/go-libp2p-noise v0.1.2 // indirect
|
||||
github.com/libp2p/go-libp2p-pubsub v0.3.6
|
||||
github.com/libp2p/go-libp2p-testing v0.1.2-0.20200422005655-8775583591d8 // indirect
|
||||
github.com/mattn/go-colorable v0.1.6 // indirect
|
||||
github.com/mattn/go-sqlite3 v1.9.0
|
||||
github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1
|
||||
github.com/multiformats/go-multiaddr v0.3.1
|
||||
github.com/olekukonko/tablewriter v0.0.4 // indirect
|
||||
github.com/prometheus/common v0.10.0 // indirect
|
||||
github.com/onsi/ginkgo v1.14.0 // indirect
|
||||
github.com/polydawn/refmt v0.0.0-20190809202753-05966cbd336a // indirect
|
||||
github.com/raulk/clock v1.1.0
|
||||
github.com/rjeczalik/notify v0.9.2 // indirect
|
||||
github.com/rs/cors v1.7.0 // indirect
|
||||
github.com/rs/zerolog v1.20.0 // indirect
|
||||
github.com/sirupsen/logrus v1.7.0
|
||||
github.com/smartystreets/assertions v1.0.1 // indirect
|
||||
github.com/spf13/viper v1.7.1
|
||||
@ -47,13 +53,16 @@ require (
|
||||
github.com/steakknife/bloomfilter v0.0.0-20180922174646-6819c0d2a570 // indirect
|
||||
github.com/steakknife/hamming v0.0.0-20180906055917-c99c65617cd3 // indirect
|
||||
github.com/stretchr/testify v1.6.1
|
||||
github.com/supranational/blst v0.1.1 // indirect
|
||||
github.com/tyler-smith/go-bip39 v1.0.2 // indirect
|
||||
github.com/warpfork/go-wish v0.0.0-20200122115046-b9ea61034e4a // indirect
|
||||
github.com/whyrusleeping/cbor-gen v0.0.0-20200826160007-0b9f6c5fb163
|
||||
github.com/wsddn/go-ecdh v0.0.0-20161211032359-48726bab9208 // indirect
|
||||
github.com/xorcare/golden v0.6.1-0.20191112154924-b87f686d7542
|
||||
go.opencensus.io v0.22.4
|
||||
golang.org/x/lint v0.0.0-20200302205851-738671d3881b // indirect
|
||||
golang.org/x/net v0.0.0-20200707034311-ab3426394381 // indirect
|
||||
golang.org/x/tools v0.0.0-20200827010519-17fd2f27a9e3 // indirect
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1
|
||||
google.golang.org/protobuf v1.25.0 // 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/urfave/cli.v1 v1.20.0 // indirect
|
||||
|
@ -8,9 +8,9 @@ import (
|
||||
"github.com/Secured-Finance/dione/drand"
|
||||
)
|
||||
|
||||
// NewBeaconSchedule creates a new beacon chain schedule
|
||||
func (n *Node) NewBeaconSchedule() (beacon.Schedule, error) {
|
||||
schedule := beacon.Schedule{}
|
||||
// NewBeaconQueue creates a new beacon chain schedule
|
||||
func (n *Node) NewBeaconQueue() (beacon.Queue, error) {
|
||||
schedule := beacon.Queue{}
|
||||
bc, err := drand.NewDrandBeacon(config.ChainGenesis, config.TaskEpochInterval, n.PubSubRouter.Pubsub)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("creating drand beacon: %w", err)
|
||||
|
12
node/node.go
12
node/node.go
@ -12,7 +12,7 @@ import (
|
||||
"github.com/Secured-Finance/dione/consensus"
|
||||
"github.com/Secured-Finance/dione/pb"
|
||||
"github.com/Secured-Finance/dione/rpc"
|
||||
"github.com/Secured-Finance/dione/rpcclient"
|
||||
"github.com/Secured-Finance/dione/ethclient"
|
||||
"github.com/libp2p/go-libp2p"
|
||||
crypto "github.com/libp2p/go-libp2p-core/crypto"
|
||||
"github.com/libp2p/go-libp2p-core/host"
|
||||
@ -32,8 +32,9 @@ type Node struct {
|
||||
OracleTopic string
|
||||
Config *config.Config
|
||||
Lotus *rpc.LotusClient
|
||||
Ethereum *rpcclient.EthereumClient
|
||||
Ethereum *ethclient.EthereumClient
|
||||
ConsensusManager *consensus.PBFTConsensusManager
|
||||
MinerBase *consensus.MinerBase
|
||||
}
|
||||
|
||||
func NewNode(configPath string) (*Node, error) {
|
||||
@ -57,8 +58,13 @@ func (n *Node) setupNode(ctx context.Context, prvKey crypto.PrivKey, pexDiscover
|
||||
n.setupConsensusManager(n.Config.ConsensusMaxFaultNodes)
|
||||
}
|
||||
|
||||
func (n *Node) setupMiner() error {
|
||||
// here we do miner base setup
|
||||
return nil
|
||||
}
|
||||
|
||||
func (n *Node) setupEthereumClient() error {
|
||||
ethereum := rpcclient.NewEthereumClient()
|
||||
ethereum := ethclient.NewEthereumClient()
|
||||
n.Ethereum = ethereum
|
||||
return ethereum.Initialize(context.Background(),
|
||||
n.Config.Ethereum.GatewayAddress,
|
||||
|
49
sigs/ed25519/ed25519.go
Normal file
49
sigs/ed25519/ed25519.go
Normal file
@ -0,0 +1,49 @@
|
||||
package ed25519
|
||||
|
||||
import (
|
||||
"crypto/ed25519"
|
||||
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
"github.com/libp2p/go-libp2p-core/peer"
|
||||
|
||||
"github.com/Secured-Finance/dione/sigs"
|
||||
"github.com/Secured-Finance/dione/types"
|
||||
)
|
||||
|
||||
type ed25519Signer struct{}
|
||||
|
||||
func (ed25519Signer) GenPrivate() ([]byte, error) {
|
||||
_, privKey, err := ed25519.GenerateKey(nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return privKey.Seed(), nil
|
||||
}
|
||||
|
||||
func (ed25519Signer) ToPublic(priv []byte) ([]byte, error) {
|
||||
privKey := ed25519.NewKeyFromSeed(priv)
|
||||
pubKey := privKey.Public().(ed25519.PublicKey)
|
||||
return pubKey, nil
|
||||
}
|
||||
|
||||
func (ed25519Signer) Sign(p []byte, msg []byte) ([]byte, error) {
|
||||
privKey := ed25519.NewKeyFromSeed(p)
|
||||
return ed25519.Sign(privKey, msg), nil
|
||||
}
|
||||
|
||||
func (ed25519Signer) Verify(sig []byte, a peer.ID, msg []byte) error {
|
||||
pubKey, err := a.ExtractPublicKey()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if valid, err := pubKey.Verify(msg, sig); err != nil || !valid {
|
||||
return xerrors.Errorf("failed to verify signature")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
sigs.RegisterSignature(types.SigTypeEd25519, ed25519Signer{})
|
||||
}
|
106
sigs/sigs.go
Normal file
106
sigs/sigs.go
Normal file
@ -0,0 +1,106 @@
|
||||
package sigs
|
||||
|
||||
import (
|
||||
"context"
|
||||
fmt "fmt"
|
||||
|
||||
"github.com/libp2p/go-libp2p-core/peer"
|
||||
|
||||
"github.com/Secured-Finance/dione/types"
|
||||
"github.com/filecoin-project/go-address"
|
||||
"golang.org/x/xerrors"
|
||||
)
|
||||
|
||||
// Sign takes in signature type, private key and message. Returns a signature for that message.
|
||||
// Valid sigTypes are: "ed25519"
|
||||
func Sign(sigType types.SigType, privkey []byte, msg []byte) (*types.Signature, error) {
|
||||
sv, ok := sigs[sigType]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("cannot sign message with signature of unsupported type: %v", sigType)
|
||||
}
|
||||
|
||||
sb, err := sv.Sign(privkey, msg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &types.Signature{
|
||||
Type: sigType,
|
||||
Data: sb,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Verify verifies signatures
|
||||
func Verify(sig *types.Signature, addr peer.ID, msg []byte) error {
|
||||
if sig == nil {
|
||||
return xerrors.Errorf("signature is nil")
|
||||
}
|
||||
|
||||
sv, ok := sigs[sig.Type]
|
||||
if !ok {
|
||||
return fmt.Errorf("cannot verify signature of unsupported type: %v", sig.Type)
|
||||
}
|
||||
|
||||
return sv.Verify(sig.Data, addr, msg)
|
||||
}
|
||||
|
||||
// Generate generates private key of given type
|
||||
func Generate(sigType types.SigType) ([]byte, error) {
|
||||
sv, ok := sigs[sigType]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("cannot generate private key of unsupported type: %v", sigType)
|
||||
}
|
||||
|
||||
return sv.GenPrivate()
|
||||
}
|
||||
|
||||
// ToPublic converts private key to public key
|
||||
func ToPublic(sigType types.SigType, pk []byte) ([]byte, error) {
|
||||
sv, ok := sigs[sigType]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("cannot generate public key of unsupported type: %v", sigType)
|
||||
}
|
||||
|
||||
return sv.ToPublic(pk)
|
||||
}
|
||||
|
||||
func CheckTaskSignature(ctx context.Context, task *types.DioneTask, worker address.Address) error {
|
||||
//if task.IsValidated() {
|
||||
// return nil
|
||||
//}
|
||||
//
|
||||
//if task.BlockSig == nil {
|
||||
// return xerrors.New("block signature not present")
|
||||
//}
|
||||
//
|
||||
//sigb, err := task.SigningBytes()
|
||||
//if err != nil {
|
||||
// return xerrors.Errorf("failed to get block signing bytes: %w", err)
|
||||
//}
|
||||
//
|
||||
//err = Verify(task.BlockSig, worker, sigb)
|
||||
//if err == nil {
|
||||
// task.SetValidated()
|
||||
//}
|
||||
|
||||
// TODO
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// SigShim is used for introducing signature functions
|
||||
type SigShim interface {
|
||||
GenPrivate() ([]byte, error)
|
||||
ToPublic(pk []byte) ([]byte, error)
|
||||
Sign(pk []byte, msg []byte) ([]byte, error)
|
||||
Verify(sig []byte, a peer.ID, msg []byte) error
|
||||
}
|
||||
|
||||
var sigs map[types.SigType]SigShim
|
||||
|
||||
// RegisterSignature should be only used during init
|
||||
func RegisterSignature(typ types.SigType, vs SigShim) {
|
||||
if sigs == nil {
|
||||
sigs = make(map[types.SigType]SigShim)
|
||||
}
|
||||
sigs[typ] = vs
|
||||
}
|
@ -4,8 +4,8 @@ import (
|
||||
"math/big"
|
||||
"time"
|
||||
|
||||
"github.com/Secured-Finance/dione/ethclient"
|
||||
"github.com/Secured-Finance/dione/lib"
|
||||
"github.com/Secured-Finance/dione/rpcclient"
|
||||
"github.com/Secured-Finance/dione/types"
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
validation "github.com/go-ozzo/ozzo-validation"
|
||||
@ -15,17 +15,17 @@ type DioneStakeInfo struct {
|
||||
ID int
|
||||
MinerStake *big.Int
|
||||
TotalStake *big.Int
|
||||
MinerWallet string
|
||||
MinerAddress string
|
||||
MinerEthWallet string
|
||||
Timestamp time.Time
|
||||
Ethereum *rpcclient.EthereumClient
|
||||
Ethereum *ethclient.EthereumClient
|
||||
}
|
||||
|
||||
func NewDioneStakeInfo(minerStake, totalStake *big.Int, minerWallet, minerEthWallet string, ethereumClient *rpcclient.EthereumClient) *DioneStakeInfo {
|
||||
func NewDioneStakeInfo(minerStake, totalStake *big.Int, minerWallet, minerEthWallet string, ethereumClient *ethclient.EthereumClient) *DioneStakeInfo {
|
||||
return &DioneStakeInfo{
|
||||
MinerStake: minerStake,
|
||||
TotalStake: totalStake,
|
||||
MinerWallet: minerWallet,
|
||||
MinerAddress: minerWallet,
|
||||
MinerEthWallet: minerEthWallet,
|
||||
Ethereum: ethereumClient,
|
||||
}
|
||||
@ -63,10 +63,10 @@ func (s *Store) CreateDioneStakeInfo(stakeStore *DioneStakeInfo) error {
|
||||
now := lib.Clock.Now()
|
||||
|
||||
return s.db.QueryRow(
|
||||
"INSERT INTO staking (miner_stake, total_stake, miner_wallet, miner_eth_wallet, timestamp) VALUES ($1, $2, $3, $4, $5) RETURNING id",
|
||||
"INSERT INTO staking (miner_stake, total_stake, miner_address, miner_eth_wallet, timestamp) VALUES ($1, $2, $3, $4, $5) RETURNING id",
|
||||
stakeStore.MinerStake,
|
||||
stakeStore.TotalStake,
|
||||
stakeStore.MinerWallet,
|
||||
stakeStore.MinerAddress,
|
||||
stakeStore.MinerEthWallet,
|
||||
now,
|
||||
).Scan(&stakeStore.ID)
|
||||
@ -75,7 +75,7 @@ func (s *Store) CreateDioneStakeInfo(stakeStore *DioneStakeInfo) error {
|
||||
func (s *Store) GetLastStakeInfo(wallet, ethWallet string) (*DioneStakeInfo, error) {
|
||||
var stake *DioneStakeInfo
|
||||
if err := s.db.Select(&stake,
|
||||
`SELECT miner_stake, total_stake, miner_wallet, miner_eth_wallet, timestamp FROM staking ORDER BY TIMESTAMP DESC LIMIT 1 WHERE miner_wallet=$1, miner_eth_wallet=$2`,
|
||||
`SELECT miner_stake, total_stake, miner_address, miner_eth_wallet, timestamp FROM staking ORDER BY TIMESTAMP DESC LIMIT 1 WHERE miner_address=$1, miner_eth_wallet=$2`,
|
||||
wallet,
|
||||
ethWallet,
|
||||
); err != nil {
|
||||
@ -91,7 +91,7 @@ func (s *DioneStakeInfo) Validate() error {
|
||||
s,
|
||||
validation.Field(&s.MinerStake, validation.Required, validation.By(types.ValidateBigInt(s.MinerStake))),
|
||||
validation.Field(&s.TotalStake, validation.Required, validation.By(types.ValidateBigInt(s.TotalStake))),
|
||||
validation.Field(&s.MinerWallet, validation.Required),
|
||||
validation.Field(&s.MinerAddress, validation.Required),
|
||||
validation.Field(&s.MinerEthWallet, validation.Required),
|
||||
)
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ package store
|
||||
import (
|
||||
"github.com/Secured-Finance/dione/node"
|
||||
"github.com/jmoiron/sqlx"
|
||||
_ "github.com/mattn/go-sqlite3"
|
||||
)
|
||||
|
||||
type Store struct {
|
||||
@ -29,7 +30,7 @@ func NewStore(node *node.Node, genesisTs uint64) (*Store, error) {
|
||||
}
|
||||
|
||||
func newDB(databaseURL string) (*sqlx.DB, error) {
|
||||
db, err := sqlx.Connect("postgres", databaseURL)
|
||||
db, err := sqlx.Connect("sqlite3", databaseURL)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -4,7 +4,6 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"github.com/filecoin-project/go-state-types/crypto"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
@ -17,8 +16,7 @@ var (
|
||||
type KeyType string
|
||||
|
||||
const (
|
||||
KTBLS KeyType = "bls"
|
||||
KTSecp256k1 KeyType = "secp256k1"
|
||||
KTEd25519 KeyType = "ed25519"
|
||||
)
|
||||
|
||||
func (kt *KeyType) UnmarshalJSON(bb []byte) error {
|
||||
@ -38,13 +36,11 @@ func (kt *KeyType) UnmarshalJSON(bb []byte) error {
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not unmarshal KeyType either as string nor integer: %w", err)
|
||||
}
|
||||
bst := crypto.SigType(b)
|
||||
bst := SigType(b)
|
||||
|
||||
switch bst {
|
||||
case crypto.SigTypeBLS:
|
||||
*kt = KTBLS
|
||||
case crypto.SigTypeSecp256k1:
|
||||
*kt = KTSecp256k1
|
||||
case SigTypeEd25519:
|
||||
*kt = KTEd25519
|
||||
default:
|
||||
return fmt.Errorf("unknown sigtype: %d", bst)
|
||||
}
|
||||
|
107
types/signature.go
Normal file
107
types/signature.go
Normal file
@ -0,0 +1,107 @@
|
||||
package types
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"math"
|
||||
|
||||
cbg "github.com/whyrusleeping/cbor-gen"
|
||||
)
|
||||
|
||||
type SigType byte
|
||||
|
||||
const (
|
||||
SigTypeUnknown = SigType(math.MaxUint8)
|
||||
|
||||
SigTypeEd25519 = SigType(iota)
|
||||
)
|
||||
|
||||
const SignatureMaxLength = 200
|
||||
|
||||
type Signature struct {
|
||||
Type SigType
|
||||
Data []byte
|
||||
}
|
||||
|
||||
func (s *Signature) Equals(o *Signature) bool {
|
||||
if s == nil || o == nil {
|
||||
return s == o
|
||||
}
|
||||
return s.Type == o.Type && bytes.Equal(s.Data, o.Data)
|
||||
}
|
||||
|
||||
func (s *Signature) MarshalCBOR(w io.Writer) error {
|
||||
if s == nil {
|
||||
_, err := w.Write(cbg.CborNull)
|
||||
return err
|
||||
}
|
||||
|
||||
header := cbg.CborEncodeMajorType(cbg.MajByteString, uint64(len(s.Data)+1))
|
||||
if _, err := w.Write(header); err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := w.Write([]byte{byte(s.Type)}); err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := w.Write(s.Data); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Signature) UnmarshalCBOR(br io.Reader) error {
|
||||
maj, l, err := cbg.CborReadHeader(br)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if maj != cbg.MajByteString {
|
||||
return fmt.Errorf("not a byte string")
|
||||
}
|
||||
if l > SignatureMaxLength {
|
||||
return fmt.Errorf("string too long")
|
||||
}
|
||||
if l == 0 {
|
||||
return fmt.Errorf("string empty")
|
||||
}
|
||||
buf := make([]byte, l)
|
||||
if _, err = io.ReadFull(br, buf); err != nil {
|
||||
return err
|
||||
}
|
||||
switch SigType(buf[0]) {
|
||||
default:
|
||||
return fmt.Errorf("invalid signature type in cbor input: %d", buf[0])
|
||||
case SigTypeEd25519:
|
||||
s.Type = SigTypeEd25519
|
||||
}
|
||||
s.Data = buf[1:]
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Signature) MarshalBinary() ([]byte, error) {
|
||||
bs := make([]byte, len(s.Data)+1)
|
||||
bs[0] = byte(s.Type)
|
||||
copy(bs[1:], s.Data)
|
||||
return bs, nil
|
||||
}
|
||||
|
||||
func (s *Signature) UnmarshalBinary(bs []byte) error {
|
||||
if len(bs) > SignatureMaxLength {
|
||||
return fmt.Errorf("invalid signature bytes, too long (%d)", len(bs))
|
||||
}
|
||||
if len(bs) == 0 {
|
||||
return fmt.Errorf("invalid signature bytes of length 0")
|
||||
}
|
||||
switch SigType(bs[0]) {
|
||||
default:
|
||||
// Do not error during unmarshal but leave a standard value.
|
||||
// unmarshal(marshal(zero valued sig)) is valuable for test
|
||||
// and type needs to be checked by caller anyway.
|
||||
s.Type = SigTypeUnknown
|
||||
case SigTypeEd25519:
|
||||
s.Type = SigTypeEd25519
|
||||
}
|
||||
s.Data = bs[1:]
|
||||
return nil
|
||||
}
|
@ -3,9 +3,17 @@ package types
|
||||
import (
|
||||
"strconv"
|
||||
|
||||
"github.com/libp2p/go-libp2p-core/peer"
|
||||
|
||||
"github.com/Secured-Finance/dione/config"
|
||||
"github.com/filecoin-project/go-address"
|
||||
"github.com/filecoin-project/go-state-types/crypto"
|
||||
)
|
||||
|
||||
type TaskType byte
|
||||
|
||||
const (
|
||||
EthereumTaskType = TaskType(iota)
|
||||
FilecoinTaskType
|
||||
SolanaTaskType
|
||||
)
|
||||
|
||||
// TaskEpoch represents the timestamp of Task computed by the Dione miner
|
||||
@ -20,11 +28,12 @@ func (e TaskEpoch) String() string {
|
||||
// DioneTask represents the values of task computation
|
||||
// Miner is an address of miner node
|
||||
type DioneTask struct {
|
||||
Miner address.Address
|
||||
Type TaskType
|
||||
Miner peer.ID
|
||||
Ticket *Ticket
|
||||
ElectionProof *ElectionProof
|
||||
BeaconEntries []BeaconEntry
|
||||
Signature *crypto.Signature
|
||||
Signature *Signature
|
||||
Epoch TaskEpoch
|
||||
Payload []byte
|
||||
}
|
||||
|
@ -3,22 +3,23 @@ package wallet
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/libp2p/go-libp2p-core/crypto"
|
||||
"github.com/libp2p/go-libp2p-core/peer"
|
||||
|
||||
"github.com/Secured-Finance/dione/sigs"
|
||||
"github.com/Secured-Finance/dione/types"
|
||||
"github.com/filecoin-project/go-address"
|
||||
"github.com/filecoin-project/go-state-types/crypto"
|
||||
"github.com/filecoin-project/lotus/lib/sigs"
|
||||
)
|
||||
|
||||
type Key struct {
|
||||
types.KeyInfo
|
||||
|
||||
PublicKey []byte
|
||||
Address address.Address
|
||||
Address peer.ID
|
||||
}
|
||||
|
||||
func GenerateKey(typ types.KeyType) (*Key, error) {
|
||||
ctyp := ActSigType(typ)
|
||||
if ctyp == crypto.SigTypeUnknown {
|
||||
if ctyp == types.SigTypeUnknown {
|
||||
return nil, fmt.Errorf("unknown sig type: %s", typ)
|
||||
}
|
||||
pk, err := sigs.Generate(ctyp)
|
||||
@ -46,16 +47,15 @@ func NewKey(keyinfo types.KeyInfo) (*Key, error) {
|
||||
}
|
||||
|
||||
switch k.Type {
|
||||
case types.KTSecp256k1:
|
||||
k.Address, err = address.NewSecp256k1Address(k.PublicKey)
|
||||
case types.KTEd25519:
|
||||
pubKey, err := crypto.UnmarshalEd25519PublicKey(k.PublicKey)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to unmarshal ed25519 public key: %w", err)
|
||||
}
|
||||
k.Address, err = peer.IDFromPublicKey(pubKey)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("converting Secp256k1 to address: %w", err)
|
||||
}
|
||||
case types.KTBLS:
|
||||
k.Address, err = address.NewBLSAddress(k.PublicKey)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("converting BLS to address: %w", err)
|
||||
}
|
||||
default:
|
||||
return nil, fmt.Errorf("unsupported key type: %s", k.Type)
|
||||
}
|
||||
@ -63,13 +63,11 @@ func NewKey(keyinfo types.KeyInfo) (*Key, error) {
|
||||
|
||||
}
|
||||
|
||||
func ActSigType(typ types.KeyType) crypto.SigType {
|
||||
func ActSigType(typ types.KeyType) types.SigType {
|
||||
switch typ {
|
||||
case types.KTBLS:
|
||||
return crypto.SigTypeBLS
|
||||
case types.KTSecp256k1:
|
||||
return crypto.SigTypeSecp256k1
|
||||
case types.KTEd25519:
|
||||
return types.SigTypeEd25519
|
||||
default:
|
||||
return crypto.SigTypeUnknown
|
||||
return types.SigTypeUnknown
|
||||
}
|
||||
}
|
||||
|
@ -4,10 +4,11 @@ import (
|
||||
"context"
|
||||
"sync"
|
||||
|
||||
"github.com/libp2p/go-libp2p-core/peer"
|
||||
|
||||
"github.com/Secured-Finance/dione/sigs"
|
||||
"github.com/Secured-Finance/dione/types"
|
||||
"github.com/filecoin-project/go-address"
|
||||
"github.com/filecoin-project/go-state-types/crypto"
|
||||
"github.com/filecoin-project/lotus/lib/sigs"
|
||||
"github.com/sirupsen/logrus"
|
||||
"golang.org/x/xerrors"
|
||||
)
|
||||
@ -18,7 +19,7 @@ const (
|
||||
)
|
||||
|
||||
type LocalWallet struct {
|
||||
keys map[address.Address]*Key
|
||||
keys map[peer.ID]*Key
|
||||
keystore types.KeyStore
|
||||
|
||||
lk sync.Mutex
|
||||
@ -30,7 +31,7 @@ type Default interface {
|
||||
|
||||
func NewWallet(keystore types.KeyStore) (*LocalWallet, error) {
|
||||
w := &LocalWallet{
|
||||
keys: make(map[address.Address]*Key),
|
||||
keys: make(map[peer.ID]*Key),
|
||||
keystore: keystore,
|
||||
}
|
||||
|
||||
@ -38,7 +39,7 @@ func NewWallet(keystore types.KeyStore) (*LocalWallet, error) {
|
||||
}
|
||||
|
||||
func KeyWallet(keys ...*Key) *LocalWallet {
|
||||
m := make(map[address.Address]*Key)
|
||||
m := make(map[peer.ID]*Key)
|
||||
for _, key := range keys {
|
||||
m[key.Address] = key
|
||||
}
|
||||
@ -48,7 +49,7 @@ func KeyWallet(keys ...*Key) *LocalWallet {
|
||||
}
|
||||
}
|
||||
|
||||
func (w *LocalWallet) WalletSign(ctx context.Context, addr address.Address, msg []byte) (*crypto.Signature, error) {
|
||||
func (w *LocalWallet) WalletSign(ctx context.Context, addr peer.ID, msg []byte) (*types.Signature, error) {
|
||||
ki, err := w.findKey(addr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -60,7 +61,7 @@ func (w *LocalWallet) WalletSign(ctx context.Context, addr address.Address, msg
|
||||
return sigs.Sign(ActSigType(ki.Type), ki.PrivateKey, msg)
|
||||
}
|
||||
|
||||
func (w *LocalWallet) findKey(addr address.Address) (*Key, error) {
|
||||
func (w *LocalWallet) findKey(addr peer.ID) (*Key, error) {
|
||||
w.lk.Lock()
|
||||
defer w.lk.Unlock()
|
||||
|
||||
@ -88,7 +89,7 @@ func (w *LocalWallet) findKey(addr address.Address) (*Key, error) {
|
||||
return k, nil
|
||||
}
|
||||
|
||||
func (w *LocalWallet) tryFind(addr address.Address) (types.KeyInfo, error) {
|
||||
func (w *LocalWallet) tryFind(addr peer.ID) (types.KeyInfo, error) {
|
||||
|
||||
ki, err := w.keystore.Get(KNamePrefix + addr.String())
|
||||
if err == nil {
|
||||
@ -122,52 +123,52 @@ func (w *LocalWallet) tryFind(addr address.Address) (types.KeyInfo, error) {
|
||||
return ki, nil
|
||||
}
|
||||
|
||||
func (w *LocalWallet) GetDefault() (address.Address, error) {
|
||||
func (w *LocalWallet) GetDefault() (peer.ID, error) {
|
||||
w.lk.Lock()
|
||||
defer w.lk.Unlock()
|
||||
|
||||
ki, err := w.keystore.Get(KDefault)
|
||||
if err != nil {
|
||||
return address.Undef, xerrors.Errorf("failed to get default key: %w", err)
|
||||
return "", xerrors.Errorf("failed to get default key: %w", err)
|
||||
}
|
||||
|
||||
k, err := NewKey(ki)
|
||||
if err != nil {
|
||||
return address.Undef, xerrors.Errorf("failed to read default key from keystore: %w", err)
|
||||
return "", xerrors.Errorf("failed to read default key from keystore: %w", err)
|
||||
}
|
||||
|
||||
return k.Address, nil
|
||||
}
|
||||
|
||||
func (w *LocalWallet) WalletNew(ctx context.Context, typ types.KeyType) (address.Address, error) {
|
||||
func (w *LocalWallet) WalletNew(ctx context.Context, typ types.KeyType) (peer.ID, error) {
|
||||
w.lk.Lock()
|
||||
defer w.lk.Unlock()
|
||||
|
||||
k, err := GenerateKey(typ)
|
||||
if err != nil {
|
||||
return address.Undef, err
|
||||
return "", err
|
||||
}
|
||||
|
||||
if err := w.keystore.Put(KNamePrefix+k.Address.String(), k.KeyInfo); err != nil {
|
||||
return address.Undef, xerrors.Errorf("saving to keystore: %w", err)
|
||||
return "", xerrors.Errorf("saving to keystore: %w", err)
|
||||
}
|
||||
w.keys[k.Address] = k
|
||||
|
||||
_, err = w.keystore.Get(KDefault)
|
||||
if err != nil {
|
||||
if !xerrors.Is(err, types.ErrKeyInfoNotFound) {
|
||||
return address.Undef, err
|
||||
return "", err
|
||||
}
|
||||
|
||||
if err := w.keystore.Put(KDefault, k.KeyInfo); err != nil {
|
||||
return address.Undef, xerrors.Errorf("failed to set new key as default: %w", err)
|
||||
return "", xerrors.Errorf("failed to set new key as default: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
return k.Address, nil
|
||||
}
|
||||
|
||||
func (w *LocalWallet) WalletHas(ctx context.Context, addr address.Address) (bool, error) {
|
||||
func (w *LocalWallet) WalletHas(ctx context.Context, addr peer.ID) (bool, error) {
|
||||
k, err := w.findKey(addr)
|
||||
if err != nil {
|
||||
return false, err
|
||||
|
Loading…
Reference in New Issue
Block a user