add: staking store db integration, task mining execution
This commit is contained in:
parent
9219e483a1
commit
239e54b0dd
@ -1,6 +1,8 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
@ -13,6 +15,7 @@ type Config struct {
|
||||
Ethereum EthereumConfig `mapstructure:"ethereum"`
|
||||
Filecoin FilecoinConfig `mapstructure:"filecoin"`
|
||||
PubSub PubSubConfig `mapstructure:"pubSub"`
|
||||
Store StoreConfig `mapstructure:"store"`
|
||||
}
|
||||
|
||||
type EthereumConfig struct {
|
||||
@ -31,8 +34,17 @@ type PubSubConfig struct {
|
||||
ProtocolID string `mapstructure:"protocolID"`
|
||||
}
|
||||
|
||||
type StoreConfig struct {
|
||||
DatabaseURL string `mapstructure:"database_url"`
|
||||
}
|
||||
|
||||
// NewConfig creates a new config based on default values or provided .env file
|
||||
func NewConfig(configPath string) (*Config, error) {
|
||||
dbName := "dione"
|
||||
username := "user"
|
||||
password := "password"
|
||||
dbURL := fmt.Sprintf("host=localhost user=%s password=%s dbname=%s sslmode=disable", username, password, dbName)
|
||||
|
||||
cfg := &Config{
|
||||
ListenAddr: "localhost",
|
||||
ListenPort: ":8000",
|
||||
@ -45,6 +57,9 @@ func NewConfig(configPath string) (*Config, error) {
|
||||
PubSub: PubSubConfig{
|
||||
ProtocolID: "p2p-oracle",
|
||||
},
|
||||
Store: StoreConfig{
|
||||
DatabaseURL: dbURL,
|
||||
},
|
||||
}
|
||||
|
||||
viper.SetConfigFile(configPath)
|
||||
|
@ -13,18 +13,6 @@ import (
|
||||
"golang.org/x/xerrors"
|
||||
)
|
||||
|
||||
type MinerWallet interface {
|
||||
WalletSign(context.Context, address.Address, []byte) (*crypto.Signature, error)
|
||||
}
|
||||
|
||||
type MinerBase struct {
|
||||
MinerStake types.BigInt
|
||||
NetworkStake types.BigInt
|
||||
WorkerKey address.Address
|
||||
PrevBeaconEntry types.BeaconEntry
|
||||
BeaconEntries []types.BeaconEntry
|
||||
}
|
||||
|
||||
type SignFunc func(context.Context, address.Address, []byte) (*crypto.Signature, error)
|
||||
|
||||
func ComputeVRF(ctx context.Context, sign SignFunc, worker address.Address, sigInput []byte) ([]byte, error) {
|
||||
@ -57,7 +45,7 @@ func VerifyVRF(ctx context.Context, worker address.Address, vrfBase, vrfproof []
|
||||
}
|
||||
|
||||
func IsRoundWinner(ctx context.Context, round types.TaskEpoch,
|
||||
worker address.Address, brand types.BeaconEntry, mbi *MinerBase, a MinerWallet) (*types.ElectionProof, error) {
|
||||
worker address.Address, brand types.BeaconEntry, mb *MinerBase, a MinerAPI) (*types.ElectionProof, error) {
|
||||
|
||||
buf := new(bytes.Buffer)
|
||||
if err := worker.MarshalCBOR(buf); err != nil {
|
||||
@ -69,13 +57,13 @@ func IsRoundWinner(ctx context.Context, round types.TaskEpoch,
|
||||
return nil, xerrors.Errorf("failed to draw randomness: %w", err)
|
||||
}
|
||||
|
||||
vrfout, err := ComputeVRF(ctx, a.WalletSign, mbi.WorkerKey, electionRand)
|
||||
vrfout, err := ComputeVRF(ctx, a.WalletSign, mb.WorkerKey, electionRand)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("failed to compute VRF: %w", err)
|
||||
}
|
||||
|
||||
ep := &types.ElectionProof{VRFProof: vrfout}
|
||||
j := ep.ComputeWinCount(mbi.MinerStake, mbi.NetworkStake)
|
||||
j := ep.ComputeWinCount(mb.MinerStake, mb.NetworkStake)
|
||||
ep.WinCount = j
|
||||
if j < 1 {
|
||||
return nil, nil
|
||||
|
110
consensus/miner.go
Normal file
110
consensus/miner.go
Normal file
@ -0,0 +1,110 @@
|
||||
package consensus
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
|
||||
"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
|
||||
api MinerAPI
|
||||
}
|
||||
|
||||
type MinerAPI interface {
|
||||
WalletSign(context.Context, address.Address, []byte) (*crypto.Signature, error)
|
||||
// TODO: get miner base based on epoch;
|
||||
}
|
||||
|
||||
type MinerBase struct {
|
||||
MinerStake types.BigInt
|
||||
NetworkStake types.BigInt
|
||||
WorkerKey address.Address
|
||||
EthWallet common.Address
|
||||
PrevBeaconEntry types.BeaconEntry
|
||||
BeaconEntries []types.BeaconEntry
|
||||
NullRounds types.TaskEpoch
|
||||
}
|
||||
|
||||
type MiningBase struct {
|
||||
epoch types.TaskEpoch
|
||||
nullRounds types.TaskEpoch
|
||||
}
|
||||
|
||||
func NewMinerBase(minerStake, networkStake types.BigInt, minerWallet address.Address,
|
||||
minerEthWallet common.Address, prev types.BeaconEntry, entries []types.BeaconEntry) *MinerBase {
|
||||
return &MinerBase{
|
||||
MinerStake: minerStake,
|
||||
NetworkStake: networkStake,
|
||||
WorkerKey: minerWallet,
|
||||
EthWallet: minerEthWallet,
|
||||
PrevBeaconEntry: prev,
|
||||
BeaconEntries: entries,
|
||||
}
|
||||
}
|
||||
|
||||
func NewMiningBase() *MiningBase {
|
||||
return &MiningBase{
|
||||
nullRounds: 0,
|
||||
}
|
||||
}
|
||||
|
||||
// Start, Stop mining functions
|
||||
|
||||
func (m *Miner) MineTask(ctx context.Context, base *MiningBase, mb *MinerBase) (*types.DioneTask, error) {
|
||||
round := base.epoch + base.nullRounds + 1
|
||||
logrus.Debug("attempting to mine the task at epoch: ", round)
|
||||
|
||||
prevEntry := mb.PrevBeaconEntry
|
||||
|
||||
ticket, err := m.computeTicket(ctx, &prevEntry, base, mb)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("scratching ticket failed: %w", err)
|
||||
}
|
||||
|
||||
winner, err := IsRoundWinner(ctx, round, m.address, prevEntry, mb, m.api)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("failed to check if we win next round: %w", err)
|
||||
}
|
||||
|
||||
if winner == nil {
|
||||
return nil, nil
|
||||
}
|
||||
return &types.DioneTask{
|
||||
Miner: m.address,
|
||||
Ticket: ticket,
|
||||
ElectionProof: winner,
|
||||
BeaconEntries: mb.BeaconEntries,
|
||||
// TODO: signature
|
||||
Height: 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)
|
||||
}
|
||||
|
||||
round := base.epoch + base.nullRounds + 1
|
||||
|
||||
input, err := DrawRandomness(brand.Data, crypto.DomainSeparationTag_TicketProduction, round-types.TicketRandomnessLookback, buf.Bytes())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
vrfOut, err := ComputeVRF(ctx, m.api.WalletSign, mb.WorkerKey, input)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &types.Ticket{
|
||||
VRFProof: vrfOut,
|
||||
}, nil
|
||||
}
|
1
go.mod
1
go.mod
@ -21,6 +21,7 @@ require (
|
||||
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e // indirect
|
||||
github.com/google/uuid v1.1.1
|
||||
github.com/gopherjs/gopherjs v0.0.0-20190812055157-5d271430af9f // indirect
|
||||
github.com/jmoiron/sqlx v1.2.0
|
||||
github.com/karalabe/usb v0.0.0-20191104083709-911d15fe12a9 // indirect
|
||||
github.com/libp2p/go-libp2p v0.11.0
|
||||
github.com/libp2p/go-libp2p-core v0.6.1
|
||||
|
4
go.sum
4
go.sum
@ -680,6 +680,8 @@ github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M
|
||||
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
|
||||
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
|
||||
github.com/jmespath/go-jmespath v0.3.0/go.mod h1:9QtRXoHjLGCJ5IBSaohpXITPlowMeeYCZ7fLUTSywik=
|
||||
github.com/jmoiron/sqlx v1.2.0 h1:41Ip0zITnmWNR/vHV+S4m+VoUivnWY5E4OJfLZjCJMA=
|
||||
github.com/jmoiron/sqlx v1.2.0/go.mod h1:1FEQNm3xlJgrMD+FBdI9+xvCksHtbpVBBw5dYhBSsks=
|
||||
github.com/joeshaw/multierror v0.0.0-20140124173710-69b34d4ec901 h1:rp+c0RAYOWj8l6qbCUTSiRLG/iKnW3K3/QfPPuSsBt4=
|
||||
github.com/joeshaw/multierror v0.0.0-20140124173710-69b34d4ec901/go.mod h1:Z86h9688Y0wesXCyonoVr47MasHilkuLMqGhRZ4Hpak=
|
||||
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
|
||||
@ -730,6 +732,7 @@ github.com/kr/pty v1.1.3/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
|
||||
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||
github.com/lib/pq v1.7.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
||||
github.com/libp2p/go-addr-util v0.0.1/go.mod h1:4ac6O7n9rIAKB1dnd+s8IbbMXkt+oBpzX4/+RACcnlQ=
|
||||
github.com/libp2p/go-addr-util v0.0.2 h1:7cWK5cdA5x72jX0g8iLrQWm5TRJZ6CzGdPEhWj7plWU=
|
||||
@ -1075,6 +1078,7 @@ github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Ky
|
||||
github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
|
||||
github.com/mattn/go-runewidth v0.0.7 h1:Ei8KR0497xHyKJPAv59M1dkC+rOZCMBJ+t3fZ+twI54=
|
||||
github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
||||
github.com/mattn/go-sqlite3 v1.9.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
|
||||
github.com/mattn/go-xmlrpc v0.0.3/go.mod h1:mqc2dz7tP5x5BKlCahN/n+hs7OSZKJkS9JsHNBRlrxA=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||
|
@ -17,6 +17,7 @@ import (
|
||||
// TODO: change artifacts for other contracts
|
||||
type EthereumClient struct {
|
||||
client *ethclient.Client
|
||||
ethAddress *common.Address
|
||||
authTransactor *bind.TransactOpts
|
||||
oracleEmitter *oracleemitter.OracleEmitterSession
|
||||
aggregator *aggregator.AggregatorSession
|
||||
@ -53,6 +54,7 @@ func (c *EthereumClient) Initialize(ctx context.Context, url, privateKey, oracle
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
c.ethAddress = &c.authTransactor.From
|
||||
authTransactor := bind.NewKeyedTransactor(ecdsaKey)
|
||||
c.authTransactor = authTransactor
|
||||
|
||||
@ -158,26 +160,6 @@ func (c *EthereumClient) Initialize(ctx context.Context, url, privateKey, oracle
|
||||
// return TxHash
|
||||
// }
|
||||
|
||||
// func (c *EthereumClient) GenerateAddressFromPrivateKey(private_key string) string {
|
||||
// privateKey, err := crypto.HexToECDSA(private_key)
|
||||
// if err != nil {
|
||||
// c.Logger.Fatal("Failed to generate private key", err)
|
||||
// }
|
||||
|
||||
// publicKey := privateKey.Public()
|
||||
// publicKeyECDSA, ok := publicKey.(*ecdsa.PublicKey)
|
||||
// if !ok {
|
||||
// c.Logger.Fatal("cannot assert type: publicKey is not of type *ecdsa.PublicKey")
|
||||
// }
|
||||
|
||||
// publicKeyBytes := crypto.FromECDSAPub(publicKeyECDSA)
|
||||
// c.Logger.Info(hexutil.Encode(publicKeyBytes)[4:])
|
||||
|
||||
// address := crypto.PubkeyToAddress(*publicKeyECDSA).Hex()
|
||||
|
||||
// return address
|
||||
// }
|
||||
|
||||
func (c *EthereumClient) SubscribeOnOracleEvents(incomingEventsChan chan *oracleemitter.OracleEmitterNewOracleRequest) (event.Subscription, error) {
|
||||
requestsFilter := c.oracleEmitter.Contract.OracleEmitterFilterer
|
||||
subscription, err := requestsFilter.WatchNewOracleRequest(&bind.WatchOpts{
|
||||
@ -224,6 +206,9 @@ func (c *EthereumClient) SubmitRequestAnswer(reqID *big.Int, data string, callba
|
||||
return nil
|
||||
}
|
||||
|
||||
// Getting total stake in DioneStaking contract, this function could
|
||||
// be used for storing the total stake and veryfing the stake tokens
|
||||
// on new tasks
|
||||
func (c *EthereumClient) GetTotalStake() (*big.Int, error) {
|
||||
totalStake, err := c.dioneStaking.TotalStake()
|
||||
if err != nil {
|
||||
@ -232,6 +217,9 @@ func (c *EthereumClient) GetTotalStake() (*big.Int, error) {
|
||||
return totalStake, nil
|
||||
}
|
||||
|
||||
// Getting miner stake in DioneStaking contract, this function could
|
||||
// be used for storing the miner's stake and veryfing the stake tokens
|
||||
// on new tasks
|
||||
func (c *EthereumClient) GetMinerStake(minerAddress common.Address) (*big.Int, error) {
|
||||
minerStake, err := c.dioneStaking.MinerStake(minerAddress)
|
||||
if err != nil {
|
||||
|
35
rpcclient/wallet.go
Normal file
35
rpcclient/wallet.go
Normal file
@ -0,0 +1,35 @@
|
||||
package rpcclient
|
||||
|
||||
import (
|
||||
"crypto/ecdsa"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
func GenerateEthWalletAddressFromPrivateKey(private_key string) common.Address {
|
||||
privateKey, err := crypto.HexToECDSA(private_key)
|
||||
if err != nil {
|
||||
logrus.Fatal("Failed to generate private key", err)
|
||||
}
|
||||
|
||||
publicKey := privateKey.Public()
|
||||
publicKeyECDSA, ok := publicKey.(*ecdsa.PublicKey)
|
||||
if !ok {
|
||||
logrus.Fatal("cannot assert type: publicKey is not of type *ecdsa.PublicKey")
|
||||
}
|
||||
|
||||
publicKeyBytes := crypto.FromECDSAPub(publicKeyECDSA)
|
||||
logrus.Info(hexutil.Encode(publicKeyBytes)[4:])
|
||||
|
||||
address := crypto.PubkeyToAddress(*publicKeyECDSA)
|
||||
|
||||
return address
|
||||
}
|
||||
|
||||
// Convert common.Address type into string for ethereum wallet
|
||||
func EthWalletToString(ethWallet common.Address) string {
|
||||
return ethWallet.Hex()
|
||||
}
|
@ -2,28 +2,37 @@ package store
|
||||
|
||||
import (
|
||||
"math/big"
|
||||
"time"
|
||||
|
||||
"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"
|
||||
)
|
||||
|
||||
// TODO: specify store for staking mechanism
|
||||
type DioneStakeInfo struct {
|
||||
ID int
|
||||
MinerStake *big.Int
|
||||
TotalStake *big.Int
|
||||
MinerWallet string
|
||||
MinerEthWallet string
|
||||
Timestamp time.Time
|
||||
Ethereum *rpcclient.EthereumClient
|
||||
}
|
||||
|
||||
func NewDioneStakeInfo(minerStake, totalStake *big.Int, ethereumClient *rpcclient.EthereumClient) *DioneStakeInfo {
|
||||
func NewDioneStakeInfo(minerStake, totalStake *big.Int, minerWallet, minerEthWallet string, ethereumClient *rpcclient.EthereumClient) *DioneStakeInfo {
|
||||
return &DioneStakeInfo{
|
||||
MinerStake: minerStake,
|
||||
TotalStake: totalStake,
|
||||
MinerWallet: minerWallet,
|
||||
MinerEthWallet: minerEthWallet,
|
||||
Ethereum: ethereumClient,
|
||||
}
|
||||
}
|
||||
|
||||
func (d *DioneStakeInfo) UpdateMinerStake(minerAddress common.Address) error {
|
||||
minerStake, err := d.Ethereum.GetMinerStake(minerAddress)
|
||||
func (d *DioneStakeInfo) UpdateMinerStake(minerEthAddress common.Address) error {
|
||||
minerStake, err := d.Ethereum.GetMinerStake(minerEthAddress)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -33,7 +42,7 @@ func (d *DioneStakeInfo) UpdateMinerStake(minerAddress common.Address) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *DioneStakeInfo) UpdateTotalStake(minerAddress common.Address) error {
|
||||
func (d *DioneStakeInfo) UpdateTotalStake() error {
|
||||
totalStake, err := d.Ethereum.GetTotalStake()
|
||||
if err != nil {
|
||||
return err
|
||||
@ -43,3 +52,46 @@ func (d *DioneStakeInfo) UpdateTotalStake(minerAddress common.Address) error {
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Put miner's staking information into the database
|
||||
func (s *Store) CreateDioneStakeInfo(stakeStore *DioneStakeInfo) error {
|
||||
|
||||
if err := stakeStore.Validate(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
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",
|
||||
stakeStore.MinerStake,
|
||||
stakeStore.TotalStake,
|
||||
stakeStore.MinerWallet,
|
||||
stakeStore.MinerEthWallet,
|
||||
now,
|
||||
).Scan(&stakeStore.ID)
|
||||
}
|
||||
|
||||
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`,
|
||||
wallet,
|
||||
ethWallet,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return stake, nil
|
||||
}
|
||||
|
||||
// Before puting the data into the database validating all required fields
|
||||
func (s *DioneStakeInfo) Validate() error {
|
||||
return validation.ValidateStruct(
|
||||
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.MinerEthWallet, validation.Required),
|
||||
)
|
||||
}
|
||||
|
@ -1,24 +1,45 @@
|
||||
package store
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
|
||||
"github.com/Secured-Finance/dione/node"
|
||||
"github.com/jmoiron/sqlx"
|
||||
)
|
||||
|
||||
type Store struct {
|
||||
db *sql.DB
|
||||
db *sqlx.DB
|
||||
node *node.Node
|
||||
genesisTs uint64
|
||||
StakeStorage DioneStakeInfo
|
||||
// genesisTask *types.DioneTask
|
||||
}
|
||||
|
||||
func NewStore(db *sql.DB, node *node.Node, genesisTs uint64) *Store {
|
||||
func NewStore(node *node.Node, genesisTs uint64) (*Store, error) {
|
||||
db, err := newDB(node.Config.Store.DatabaseURL)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
defer db.Close()
|
||||
|
||||
return &Store{
|
||||
db: db,
|
||||
node: node,
|
||||
genesisTs: genesisTs,
|
||||
}
|
||||
}, nil
|
||||
}
|
||||
|
||||
// TODO: connect data base; specify the table for stake storage; queries for stake storage
|
||||
func newDB(databaseURL string) (*sqlx.DB, error) {
|
||||
db, err := sqlx.Connect("postgres", databaseURL)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := db.Ping(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return db, nil
|
||||
}
|
||||
|
||||
// TODO: Discuss with ChronosX88 about using custom database to decrease I/O bound
|
||||
// specify the migrations for stake storage;
|
||||
|
@ -1,9 +1,11 @@
|
||||
package types
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"math/big"
|
||||
|
||||
big2 "github.com/filecoin-project/go-state-types/big"
|
||||
validation "github.com/go-ozzo/ozzo-validation"
|
||||
)
|
||||
|
||||
var EmptyInt = BigInt{}
|
||||
@ -18,3 +20,13 @@ func BigFromBytes(b []byte) BigInt {
|
||||
i := big.NewInt(0).SetBytes(b)
|
||||
return BigInt{Int: i}
|
||||
}
|
||||
|
||||
func ValidateBigInt(i *big.Int) validation.RuleFunc {
|
||||
return func(value interface{}) error {
|
||||
bigInt := i.IsInt64()
|
||||
if !bigInt {
|
||||
return errors.New("expected big integer")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
@ -11,6 +11,8 @@ import (
|
||||
// TaskEpoch represents the timestamp of Task computed by the Dione miner
|
||||
type TaskEpoch int64
|
||||
|
||||
const TicketRandomnessLookback = TaskEpoch(1)
|
||||
|
||||
func (e TaskEpoch) String() string {
|
||||
return strconv.FormatInt(int64(e), 10)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user