Skip to content

Commit

Permalink
integrate vote pool related components into eth backend (#13)
Browse files Browse the repository at this point in the history
* integrate vote pool related components into eth backend

* update

* update

* init parlia with votepool

Co-authored-by: zjubfd <[email protected]>
  • Loading branch information
calmbeing and unclezoro committed May 20, 2022
1 parent f1507cb commit 3191b13
Show file tree
Hide file tree
Showing 16 changed files with 192 additions and 88 deletions.
3 changes: 2 additions & 1 deletion cmd/geth/blsaccountcmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import (
"path/filepath"
"strings"

"github.com/ethereum/go-ethereum/cmd/utils"
"github.com/google/uuid"
"github.com/logrusorgru/aurora"
"github.com/prysmaticlabs/prysm/crypto/bls"
Expand All @@ -25,6 +24,8 @@ import (
"github.com/prysmaticlabs/prysm/validator/keymanager/imported"
keystorev4 "github.com/wealdtech/go-eth2-wallet-encryptor-keystorev4"
"gopkg.in/urfave/cli.v1"

"github.com/ethereum/go-ethereum/cmd/utils"
)

const (
Expand Down
3 changes: 3 additions & 0 deletions cmd/geth/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,9 @@ var (
utils.CatalystFlag,
utils.BlockAmountReserved,
utils.CheckSnapshotWithMPT,
utils.BLSPassWordDirFlag,
utils.BLSWalletDirFlag,
utils.VoteJournalDirFlag,
}

rpcFlags = []cli.Flag{
Expand Down
3 changes: 3 additions & 0 deletions cmd/geth/usage.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,9 @@ var AppHelpFlagGroups = []flags.FlagGroup{
utils.TriesInMemoryFlag,
utils.BlockAmountReserved,
utils.CheckSnapshotWithMPT,
utils.BLSPassWordDirFlag,
utils.BLSWalletDirFlag,
utils.VoteJournalDirFlag,
},
},
{
Expand Down
39 changes: 39 additions & 0 deletions cmd/utils/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -842,6 +842,21 @@ var (
Name: "check-snapshot-with-mpt",
Usage: "Enable checking between snapshot and MPT ",
}

BLSPassWordDirFlag = DirectoryFlag{
Name: "blspassword",
Usage: "Directory for the BLS password (default = inside the datadir)",
}

BLSWalletDirFlag = DirectoryFlag{
Name: "blswallet",
Usage: "Directory for the bls wallet path of fast finality (default = inside the datadir)",
}

VoteJournalDirFlag = DirectoryFlag{
Name: "vote-journal-path",
Usage: "Directory for the journal path of fast finality (default = inside the datadir)",
}
)

// MakeDataDir retrieves the currently requested data directory, terminating
Expand Down Expand Up @@ -1293,6 +1308,8 @@ func SetNodeConfig(ctx *cli.Context, cfg *node.Config) {
setNodeUserIdent(ctx, cfg)
setDataDir(ctx, cfg)
setSmartCard(ctx, cfg)
setBLSWalletDir(ctx, cfg)
setVoteJournalDir(ctx, cfg)

if ctx.GlobalIsSet(ExternalSignerFlag.Name) {
cfg.ExternalSigner = ctx.GlobalString(ExternalSignerFlag.Name)
Expand Down Expand Up @@ -1322,6 +1339,10 @@ func SetNodeConfig(ctx *cli.Context, cfg *node.Config) {
if ctx.GlobalIsSet(InsecureUnlockAllowedFlag.Name) {
cfg.InsecureUnlockAllowed = ctx.GlobalBool(InsecureUnlockAllowedFlag.Name)
}

if ctx.GlobalIsSet(BLSPassWordDirFlag.Name) {
cfg.BLSPassWordDir = ctx.GlobalString(BLSPassWordDirFlag.Name)
}
}

func setSmartCard(ctx *cli.Context, cfg *node.Config) {
Expand Down Expand Up @@ -1371,6 +1392,24 @@ func setDataDir(ctx *cli.Context, cfg *node.Config) {
}
}

func setVoteJournalDir(ctx *cli.Context, cfg *node.Config) {
dataDir := cfg.DataDir
if ctx.GlobalIsSet(VoteJournalDirFlag.Name) {
cfg.VoteJournalDir = ctx.GlobalString(VoteJournalDirFlag.Name)
} else {
cfg.VoteJournalDir = filepath.Join(dataDir, "voteJournal")
}
}

func setBLSWalletDir(ctx *cli.Context, cfg *node.Config) {
dataDir := cfg.DataDir
if ctx.GlobalIsSet(BLSWalletDirFlag.Name) {
cfg.BLSWalletDir = ctx.GlobalString(BLSWalletDirFlag.Name)
} else {
cfg.BLSWalletDir = filepath.Join(dataDir, "bls/wallet")
}
}

func setGPO(ctx *cli.Context, cfg *gasprice.Config, light bool) {
// If we are running the light client, apply another group
// settings for gas oracle.
Expand Down
6 changes: 5 additions & 1 deletion consensus/consensus.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,10 @@ type ChainHeaderReader interface {
GetHighestVerifiedHeader() *types.Header
}

type VotePool interface {
FetchVoteByHash(blockHash common.Hash) []*types.VoteEnvelope
}

// ChainReader defines a small collection of methods needed to access the local
// blockchain during header and/or uncle verification.
type ChainReader interface {
Expand Down Expand Up @@ -145,7 +149,7 @@ type PoSA interface {
EnoughDistance(chain ChainReader, header *types.Header) bool
IsLocalBlock(header *types.Header) bool
AllowLightProcess(chain ChainReader, currentHeader *types.Header) bool

// VerifyVote will verify if the vote comes from valid validators based on voteAddress (BLSPublicKey).
VerifyVote(chain ChainHeaderReader, vote *types.VoteEnvelope) bool
SetVotePool(votePool VotePool)
}
12 changes: 6 additions & 6 deletions consensus/parlia/parlia.go
Original file line number Diff line number Diff line change
Expand Up @@ -194,10 +194,6 @@ func ParliaRLP(header *types.Header, chainId *big.Int) []byte {
return b.Bytes()
}

type VotePool interface {
FetchVoteByHash(blockHash common.Hash) []*types.VoteEnvelope
}

// Parlia is the consensus engine of BSC
type Parlia struct {
chainConfig *params.ChainConfig // Chain config
Expand All @@ -217,7 +213,7 @@ type Parlia struct {
lock sync.RWMutex // Protects the signer fields

ethAPI *ethapi.PublicBlockChainAPI
votePool VotePool
votePool consensus.VotePool
validatorSetABI abi.ABI
slashABI abi.ABI

Expand Down Expand Up @@ -684,7 +680,7 @@ func (p *Parlia) PrepareValidators(chain consensus.ChainHeaderReader, header *ty
}

func (p *Parlia) PrepareVoteAttestation(chain consensus.ChainHeaderReader, header *types.Header) error {
if !p.chainConfig.IsBoneh(header.Number) {
if !p.chainConfig.IsBoneh(header.Number) || p.votePool == nil {
return nil
}

Expand Down Expand Up @@ -1515,6 +1511,10 @@ func (p *Parlia) applyTransaction(
return nil
}

func (p *Parlia) SetVotePool(votePool consensus.VotePool) {
p.votePool = votePool
}

// =========================== utility function ==========================
// SealHash returns the hash of a block prior to it being sealed.
func SealHash(header *types.Header, chainId *big.Int) (hash common.Hash) {
Expand Down
54 changes: 50 additions & 4 deletions core/vote/vote_manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,12 @@
package vote

import (
"context"
"io/ioutil"

"github.com/prysmaticlabs/prysm/validator/accounts/iface"
"github.com/prysmaticlabs/prysm/validator/accounts/wallet"

"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/eth/downloader"
Expand Down Expand Up @@ -43,19 +49,59 @@ type VoteManager struct {
journal *VoteJournal
}

func NewVoteManager(mux *event.TypeMux, chainconfig *params.ChainConfig, chain *core.BlockChain, journal *VoteJournal, signer *VoteSigner, pool *VotePool) (*VoteManager, error) {
func NewVoteManager(mux *event.TypeMux, chainconfig *params.ChainConfig, chain *core.BlockChain, pool *VotePool, journalPath, bLSPassWordPath, bLSWalletPath string) (*VoteManager, error) {
voteManager := &VoteManager{
mux: mux,

chain: chain,
chainconfig: chainconfig,
chainHeadCh: make(chan core.ChainHeadEvent, chainHeadChanSize),

signer: signer,
journal: journal,
pool: pool,
pool: pool,
}

dirExists, err := wallet.Exists(bLSWalletPath)
if err != nil {
log.Error("Check BLS wallet exists error: %v.", err)
}
if !dirExists {
log.Error("BLS wallet did not exists.")
}

walletPassword, err := ioutil.ReadFile(bLSPassWordPath)
if err != nil {
log.Error("Read BLS wallet password error: %v.", err)
return nil, err
}

w, err := wallet.OpenWallet(context.Background(), &wallet.Config{
WalletDir: bLSWalletPath,
WalletPassword: string(walletPassword),
})
if err != nil {
log.Error("Open BLS wallet failed: %v.", err)
return nil, err
}

km, err := w.InitializeKeymanager(context.Background(), iface.InitKeymanagerConfig{ListenForChanges: false})
if err != nil {
log.Error("Initialize key manager failed: %v.", err)
return nil, err
}

voteJournal, err := NewVoteJournal(journalPath)
if err != nil {
return nil, err
}
voteManager.journal = voteJournal

voteSigner, err := NewVoteSigner(&km)
if err != nil {
return nil, err
}
voteManager.signer = voteSigner

// Subscribe to chain head event.
voteManager.chainHeadSub = voteManager.chain.SubscribeChainHeadEvent(voteManager.chainHeadCh)

go voteManager.loop()
Expand Down
4 changes: 3 additions & 1 deletion core/vote/vote_pool.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,9 +93,11 @@ func NewVotePool(chainconfig *params.ChainConfig, chain *core.BlockChain, engine

// Subscribe events from blockchain and start the main event loop.
votePool.chainHeadSub = votePool.chain.SubscribeChainHeadEvent(votePool.chainHeadCh)
if posa, ok := engine.(consensus.PoSA); ok {
posa.SetVotePool(votePool)
}

go votePool.loop()

return votePool
}

Expand Down
60 changes: 28 additions & 32 deletions core/vote/vote_pool_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,27 +58,6 @@ var (
timeThreshold = 30
)

func setUpVoteJournal(t *testing.T) *VoteJournal {
// Create a temporary file for the votes journal
file, err := ioutil.TempFile("", "")
if err != nil {
t.Fatalf("failed to create temporary file path: %v", err)
}
journal := file.Name()
defer os.Remove(journal)

// Clean up the temporary file, we only need the path for now
file.Close()
os.Remove(journal)

voteJournal, err := NewVoteJournal(journal)
if err != nil {
t.Fatalf("failed to create temporary votes journal: %v", err)
}

return voteJournal
}

func (pool *VotePool) verifyStructureSizeOfVotePool(receivedVotes, curVotes, futureVotes, curVotesPq, futureVotesPq int) bool {
for i := 0; i < timeThreshold; i++ {
time.Sleep(1 * time.Second)
Expand All @@ -104,10 +83,7 @@ func (journal *VoteJournal) verifyJournal(size, lastLatestVoteNumber int) bool {
}

func TestVotePool(t *testing.T) {
km := setUpKeyManager(t)

// Create vote Signer
voteSigner, _ := NewVoteSigner(km)
walletPasswordDir, walletDir := setUpKeyManager(t)

// Create a database pre-initialize with a genesis block
db := rawdb.NewMemoryDatabase()
Expand All @@ -119,18 +95,29 @@ func TestVotePool(t *testing.T) {

mux := new(event.TypeMux)

// Create vote journal
voteJournal := setUpVoteJournal(t)

// Create vote pool
votePool := NewVotePool(params.TestChainConfig, chain, ethash.NewFaker())

// Create vote manager
voteManager, err := NewVoteManager(mux, params.TestChainConfig, chain, voteJournal, voteSigner, votePool)
// Create a temporary file for the votes journal
file, err := ioutil.TempFile("", "")
if err != nil {
t.Fatalf("failed to create temporary file path: %v", err)
}
journal := file.Name()
defer os.Remove(journal)

// Clean up the temporary file, we only need the path for now
file.Close()
os.Remove(journal)

voteManager, err := NewVoteManager(mux, params.TestChainConfig, chain, votePool, journal, walletPasswordDir, walletDir)
if err != nil {
t.Fatalf("failed to create vote managers")
}

voteJournal := voteManager.journal

// Send the done event of downloader
time.Sleep(10 * time.Millisecond)
mux.Post(downloader.DoneEvent{})
Expand Down Expand Up @@ -267,15 +254,24 @@ func TestVotePool(t *testing.T) {
}
}

func setUpKeyManager(t *testing.T) *keymanager.IKeymanager {
func setUpKeyManager(t *testing.T) (string, string) {
walletDir := filepath.Join(t.TempDir(), "wallet")
walletConfig := &accounts.CreateWalletConfig{
WalletCfg: &wallet.Config{
WalletDir: filepath.Join(t.TempDir(), "wallet"),
WalletDir: walletDir,
KeymanagerKind: keymanager.Imported,
WalletPassword: password,
},
SkipMnemonicConfirm: true,
}
walletPasswordDir := filepath.Join(t.TempDir(), "password")
if err := os.MkdirAll(filepath.Dir(walletPasswordDir), 0700); err != nil {
t.Fatalf("failed to create walletPassword dir: %v", err)
}
if err := ioutil.WriteFile(walletPasswordDir, []byte(password), 0600); err != nil {
t.Fatalf("failed to write wallet password dir: %v", err)
}

w, err := accounts.CreateWalletWithKeymanager(context.Background(), walletConfig)
if err != nil {
t.Fatalf("failed to create wallet: %v", err)
Expand Down Expand Up @@ -308,5 +304,5 @@ func setUpKeyManager(t *testing.T) *keymanager.IKeymanager {
Keystores: []*keymanager.Keystore{keystore},
AccountPassword: password,
})
return &km
return walletPasswordDir, walletDir
}
Loading

0 comments on commit 3191b13

Please sign in to comment.