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:
ChronosX88 2020-11-12 18:18:30 +04:00
parent 6636a279e7
commit 0b37896af9
Signed by: ChronosXYZ
GPG Key ID: 085A69A82C8C511A
20 changed files with 426 additions and 773 deletions

View File

@ -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)

View File

@ -7,15 +7,15 @@ import (
)
type Config struct {
ListenPort int `mapstructure:"listen_port"`
ListenAddr string `mapstructure:"listen_addr"`
BootstrapNodes []string `mapstructure:"bootstrap_node_multiaddr"`
Rendezvous string `mapstructure:"rendezvous"`
Ethereum EthereumConfig `mapstructure:"ethereum"`
Filecoin FilecoinConfig `mapstructure:"filecoin"`
PubSub PubSubConfig `mapstructure:"pubSub"`
Store StoreConfig `mapstructure:"store"`
ConsensusMaxFaultNodes int `mapstructure:"consensus_max_fault_nodes"`
ListenPort int `mapstructure:"listen_port"`
ListenAddr string `mapstructure:"listen_addr"`
BootstrapNodes []string `mapstructure:"bootstrap_node_multiaddr"`
Rendezvous string `mapstructure:"rendezvous"`
Ethereum EthereumConfig `mapstructure:"ethereum"`
Filecoin FilecoinConfig `mapstructure:"filecoin"`
PubSub PubSubConfig `mapstructure:"pubSub"`
Store StoreConfig `mapstructure:"store"`
ConsensusMaxFaultNodes int `mapstructure:"consensus_max_fault_nodes"`
}
type EthereumConfig struct {

View File

@ -25,12 +25,12 @@ type PBFTConsensusManager struct {
}
type ConsensusData struct {
preparedCount int
commitCount int
State ConsensusState
mutex sync.Mutex
result string
test bool
preparedCount int
commitCount int
State ConsensusState
mutex sync.Mutex
result string
test bool
onConsensusFinishCallback func(finalData string)
}
@ -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)

View File

@ -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)
}

View File

@ -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
}

View File

@ -1,4 +1,4 @@
package rpcclient
package ethclient
import (
"context"

View File

@ -1,4 +1,4 @@
package rpcclient
package ethclient
import (
"crypto/ecdsa"

31
go.mod
View File

@ -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

630
go.sum

File diff suppressed because it is too large Load Diff

View File

@ -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)

View File

@ -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
View 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
View 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
}

View File

@ -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),
)
}

View File

@ -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
}

View File

@ -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
View 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
}

View File

@ -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
}

View File

@ -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
}
}

View File

@ -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