-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
f4d468b
commit 39685da
Showing
5 changed files
with
669 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,226 @@ | ||
package store | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"regexp" | ||
|
||
"github.com/p2p-org/dkc/utils/crypto/bls" | ||
"github.com/pkg/errors" | ||
"github.com/spf13/viper" | ||
e2wallet "github.com/wealdtech/go-eth2-wallet" | ||
types "github.com/wealdtech/go-eth2-wallet-types/v2" | ||
"golang.org/x/exp/maps" | ||
) | ||
|
||
type Peers map[uint64]string | ||
type Threshold uint32 | ||
type DistributedStore struct { | ||
Type string | ||
Path string | ||
Store map[uint64]types.Store | ||
Peers Peers | ||
Threshold Threshold | ||
Passphrases [][]byte | ||
Ctx context.Context | ||
} | ||
|
||
func (s *DistributedStore) Create() error { | ||
for id, peer := range s.Peers { | ||
res, err := regexp.Compile(`:.*`) | ||
if err != nil { | ||
return err | ||
} | ||
store, err := createStore(s.Path + "/" + res.ReplaceAllString(peer, "")) | ||
if err != nil { | ||
return err | ||
} | ||
s.Store[id] = store | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func (s *DistributedStore) GetWalletsAccountsMap() (WalletAccountsMap, error) { | ||
// We assume that all distributed wallets in the store have the same accounts | ||
peers := maps.Values(s.Peers) | ||
res, err := regexp.Compile(`:.*`) | ||
if err != nil { | ||
return nil, err | ||
} | ||
wa, err := getWalletsAccountsMap(s.Ctx, s.Path+"/"+res.ReplaceAllString(peers[0], "")) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
return wa, nil | ||
} | ||
|
||
func (s *DistributedStore) CreateWallet(name string) error { | ||
for _, store := range s.Store { | ||
err := e2wallet.UseStore(store) | ||
if err != nil { | ||
return err | ||
} | ||
_, err = e2wallet.CreateWallet(name, e2wallet.WithType(s.Type)) | ||
if err != nil { | ||
return err | ||
} | ||
} | ||
return nil | ||
} | ||
|
||
func (s *DistributedStore) GetPK(w string, a string) ([]byte, error) { | ||
accounts := map[uint64][]byte{} | ||
res, err := regexp.Compile(`:.*`) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
for id, peer := range s.Peers { | ||
wallet, err := getWallet(s.Path+"/"+res.ReplaceAllString(peer, ""), w) | ||
if err != nil { | ||
return nil, err | ||
} | ||
err = wallet.(types.WalletLocker).Unlock(s.Ctx, nil) | ||
if err != nil { | ||
return nil, errors.Wrap(err, "test") | ||
} | ||
|
||
defer func() { | ||
err = wallet.(types.WalletLocker).Lock(s.Ctx) | ||
}() | ||
|
||
account, err := wallet.(types.WalletAccountByNameProvider).AccountByName(s.Ctx, a) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
key, err := getAccountPK(account, s.Ctx, s.Passphrases) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
accounts[id] = key | ||
|
||
} | ||
key, err := bls.Combine(s.Ctx, accounts) | ||
if err != nil { | ||
return nil, err | ||
} | ||
return key, nil | ||
} | ||
|
||
func (s *DistributedStore) SavePKToWallet(w string, a []byte, n string) error { | ||
res, err := regexp.Compile(`:.*`) | ||
if err != nil { | ||
return err | ||
} | ||
// Spliting PK to shards and get Public and Private Keys for each shard | ||
masterSKs, masterPKs, err := bls.Split(s.Ctx, a, uint32(s.Threshold)) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
peersIDs := maps.Keys(s.Peers) | ||
participants, err := bls.SetupParticipants(masterSKs, masterPKs, peersIDs, len(s.Peers)) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
for id, peer := range s.Peers { | ||
wallet, err := getWallet(s.Path+"/"+res.ReplaceAllString(peer, ""), w) | ||
if err != nil { | ||
return err | ||
} | ||
err = wallet.(types.WalletLocker).Unlock(s.Ctx, nil) | ||
if err != nil { | ||
return errors.Wrap(err, "test") | ||
} | ||
|
||
defer func() { | ||
err = wallet.(types.WalletLocker).Lock(s.Ctx) | ||
}() | ||
|
||
_, err = wallet.(types.WalletDistributedAccountImporter).ImportDistributedAccount( | ||
s.Ctx, | ||
n, | ||
participants[id], | ||
uint32(s.Threshold), | ||
masterPKs, | ||
s.Peers, | ||
// Always use the firts password | ||
s.Passphrases[0], | ||
) | ||
if err != nil { | ||
return err | ||
} | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func newDistributedStore(t string) (DistributedStore, error) { | ||
s := DistributedStore{} | ||
//Parse Wallet Type | ||
wt := viper.GetString(fmt.Sprintf("%s.wallet.type", t)) | ||
|
||
s.Type = wt | ||
|
||
//Parse Store Path | ||
storePath := viper.GetString(fmt.Sprintf("%s.store.path", t)) | ||
if storePath == "" { | ||
return s, errors.New("timeout is required") | ||
} | ||
s.Path = storePath | ||
|
||
//Parse Passphrases | ||
passphrases, err := getAccountsPasswords(viper.GetString(fmt.Sprintf("%s.wallet.passphrases.path", t))) | ||
if err != nil { | ||
return s, err | ||
} | ||
if len(passphrases) == 0 { | ||
return s, errors.New("timeout is requried") | ||
} | ||
s.Passphrases = passphrases | ||
|
||
//Parse Peers | ||
var peers Peers | ||
err = viper.UnmarshalKey(fmt.Sprintf("%s.wallet.peers", t), &peers) | ||
if err != nil { | ||
return s, err | ||
} | ||
|
||
//Peers list must be >= 2 | ||
if len(peers) < 2 { | ||
return s, errors.New("timeout is required") | ||
} | ||
s.Peers = peers | ||
|
||
//Parse Threshold | ||
var threshold Threshold | ||
err = viper.UnmarshalKey(fmt.Sprintf("%s.wallet.threshold", t), &threshold) | ||
if err != nil { | ||
return s, err | ||
} | ||
|
||
//Check number of peers and threshold | ||
if uint32(threshold) <= uint32(len(peers)/2) { | ||
return s, errors.New("timeout is required") | ||
} | ||
if uint32(threshold) > uint32(len(peers)) { | ||
return s, errors.New("timeout is required") | ||
} | ||
|
||
s.Threshold = threshold | ||
|
||
return s, nil | ||
} | ||
|
||
func (s *DistributedStore) GetPath() string { | ||
return s.Path | ||
} | ||
|
||
func (s *DistributedStore) GetType() string { | ||
return s.Type | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
package store | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
|
||
"github.com/pkg/errors" | ||
"github.com/spf13/viper" | ||
e2wallet "github.com/wealdtech/go-eth2-wallet" | ||
types "github.com/wealdtech/go-eth2-wallet-types/v2" | ||
) | ||
|
||
type HDStore struct { | ||
Type string | ||
Store types.Store | ||
Path string | ||
Passphrases [][]byte | ||
Wallets map[string][]string | ||
Ctx context.Context | ||
} | ||
|
||
func (s *HDStore) Create() error { | ||
store, err := createStore(s.Path) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
s.Store = store | ||
|
||
return nil | ||
} | ||
func (s *HDStore) GetWalletsAccountsMap() (WalletAccountsMap, error) { | ||
wa, err := getWalletsAccountsMap(s.Ctx, s.Path) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
return wa, nil | ||
} | ||
|
||
func (s *HDStore) CreateWallet(name string) (types.Wallet, error) { | ||
err := e2wallet.UseStore(s.Store) | ||
if err != nil { | ||
return nil, err | ||
} | ||
wallet, err := e2wallet.CreateWallet(name, e2wallet.WithType(s.Type)) | ||
if err != nil { | ||
return nil, errors.Wrap(err, "test") | ||
} | ||
return wallet, nil | ||
} | ||
|
||
func (s *HDStore) GetPK(w string, a string) ([]byte, error) { | ||
wallet, err := getWallet(s.Path, w) | ||
if err != nil { | ||
return nil, err | ||
} | ||
account, err := wallet.(types.WalletAccountByNameProvider).AccountByName(s.Ctx, a) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
key, err := getAccountPK(account, s.Ctx, s.Passphrases) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
return key, nil | ||
} | ||
|
||
func (s *HDStore) GetPath() string { | ||
return s.Path | ||
} | ||
|
||
func (s *HDStore) GetType() string { | ||
return s.Type | ||
} | ||
|
||
func newHDStore(t string) (HDStore, error) { | ||
s := HDStore{} | ||
//Parse Wallet Type | ||
wt := viper.GetString(fmt.Sprintf("%s.wallet.type", t)) | ||
s.Type = wt | ||
|
||
//Parse Store Path | ||
storePath := viper.GetString(fmt.Sprintf("%s.store.path", t)) | ||
if storePath == "" { | ||
return s, errors.New("timeout is required") | ||
} | ||
s.Path = storePath | ||
|
||
//Parse Passphrases | ||
passphrases, err := getAccountsPasswords( | ||
viper.GetString(fmt.Sprintf("%s.wallet.passphrases.path", t)), | ||
) | ||
if err != nil { | ||
return s, errors.New("timeout is required") | ||
} | ||
if len(passphrases) == 0 { | ||
return s, errors.New("timeout is requried") | ||
} | ||
s.Passphrases = passphrases | ||
|
||
return s, nil | ||
} |
Oops, something went wrong.