mirror of
https://gitlab.com/pulsechaincom/prysm-pulse.git
synced 2025-01-10 19:51:20 +00:00
77267169ea
* turn up linter to 11 * Added extra linting rules and fixed all lint issues * add deadline of 10m Former-commit-id: 632999fcaa8370516d6fe76c28c503cb2e3319b7 [formerly d4354f631b1eb4f7918cde28bf063f756ae92a54] Former-commit-id: 3aaf78a56b76850b0123d61551ac554ccecfe9ad
162 lines
5.2 KiB
Go
162 lines
5.2 KiB
Go
package notary
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
"math/big"
|
|
|
|
"github.com/ethereum/go-ethereum/accounts"
|
|
"github.com/ethereum/go-ethereum/accounts/abi/bind"
|
|
gethTypes "github.com/ethereum/go-ethereum/core/types"
|
|
"github.com/ethereum/go-ethereum/params"
|
|
"github.com/prysmaticlabs/geth-sharding/sharding/contracts"
|
|
"github.com/prysmaticlabs/geth-sharding/sharding/mainchain"
|
|
shardparams "github.com/prysmaticlabs/geth-sharding/sharding/params"
|
|
log "github.com/sirupsen/logrus"
|
|
)
|
|
|
|
// subscribeBlockHeaders checks incoming block headers and determines if
|
|
// we are an eligible notary for collations. Then, it finds the pending tx's
|
|
// from the running geth node and sorts them by descending order of gas price,
|
|
// eliminates those that ask for too much gas, and routes them over
|
|
// to the SMC to create a collation.
|
|
func subscribeBlockHeaders(reader mainchain.Reader, caller mainchain.ContractCaller, account *accounts.Account) error {
|
|
headerChan := make(chan *gethTypes.Header, 16)
|
|
|
|
_, err := reader.SubscribeNewHead(context.Background(), headerChan)
|
|
if err != nil {
|
|
return fmt.Errorf("unable to subscribe to incoming headers. %v", err)
|
|
}
|
|
|
|
log.Info("Listening for new headers...")
|
|
|
|
for {
|
|
// TODO: Error handling for getting disconnected from the client.
|
|
head := <-headerChan
|
|
// Query the current state to see if we are an eligible notary.
|
|
log.Infof("Received new header: %v", head.Number.String())
|
|
|
|
// Check if we are in the notary pool before checking if we are an eligible notary.
|
|
v, err := isAccountInNotaryPool(caller, account)
|
|
if err != nil {
|
|
return fmt.Errorf("unable to verify client in notary pool. %v", err)
|
|
}
|
|
|
|
if v {
|
|
if err := checkSMCForNotary(caller, account); err != nil {
|
|
return fmt.Errorf("unable to watch shards. %v", err)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// checkSMCForNotary checks if we are an eligible notary for
|
|
// collation for the available shards in the SMC. The function calls
|
|
// getEligibleNotary from the SMC and notary a collation if
|
|
// conditions are met.
|
|
func checkSMCForNotary(caller mainchain.ContractCaller, account *accounts.Account) error {
|
|
log.Info("Checking if we are an eligible collation notary for a shard...")
|
|
shardCount, err := caller.GetShardCount()
|
|
if err != nil {
|
|
return fmt.Errorf("can't get shard count from smc: %v", err)
|
|
}
|
|
for s := int64(0); s < shardCount; s++ {
|
|
// Checks if we are an eligible notary according to the SMC.
|
|
addr, err := caller.SMCCaller().GetNotaryInCommittee(&bind.CallOpts{}, big.NewInt(s))
|
|
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if addr == account.Address {
|
|
log.Infof("Selected as notary on shard: %d", s)
|
|
}
|
|
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// getNotaryRegistry retrieves the registry of the registered account.
|
|
func getNotaryRegistry(caller mainchain.ContractCaller, account *accounts.Account) (*contracts.Registry, error) {
|
|
|
|
var nreg contracts.Registry
|
|
nreg, err := caller.SMCCaller().NotaryRegistry(&bind.CallOpts{}, account.Address)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("unable to retrieve notary registry: %v", err)
|
|
}
|
|
|
|
return &nreg, nil
|
|
}
|
|
|
|
// isAccountInNotaryPool checks if the user is in the notary pool because
|
|
// we can't guarantee our tx for deposit will be in the next block header we receive.
|
|
// The function calls IsNotaryDeposited from the SMC and returns true if
|
|
// the user is in the notary pool.
|
|
func isAccountInNotaryPool(caller mainchain.ContractCaller, account *accounts.Account) (bool, error) {
|
|
|
|
nreg, err := getNotaryRegistry(caller, account)
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
|
|
if !nreg.Deposited {
|
|
log.Warnf("Account %s not in notary pool.", account.Address.Hex())
|
|
}
|
|
|
|
return nreg.Deposited, nil
|
|
}
|
|
|
|
// joinNotaryPool checks if the deposit flag is true and the account is a
|
|
// notary in the SMC. If the account is not in the set, it will deposit ETH
|
|
// into contract.
|
|
func joinNotaryPool(manager mainchain.ContractManager, client mainchain.EthClient) error {
|
|
if !client.DepositFlag() {
|
|
return errors.New("joinNotaryPool called when deposit flag was not set")
|
|
}
|
|
|
|
if b, err := isAccountInNotaryPool(manager, client.Account()); b || err != nil {
|
|
if b {
|
|
log.Info("Already joined notary pool")
|
|
return nil
|
|
}
|
|
return err
|
|
}
|
|
|
|
log.Info("Joining notary pool")
|
|
txOps, err := manager.CreateTXOpts(shardparams.DefaultConfig.NotaryDeposit)
|
|
if err != nil {
|
|
return fmt.Errorf("unable to initiate the deposit transaction: %v", err)
|
|
}
|
|
|
|
tx, err := manager.SMCTransactor().RegisterNotary(txOps)
|
|
if err != nil {
|
|
return fmt.Errorf("unable to deposit eth and become a notary: %v", err)
|
|
}
|
|
|
|
err = client.WaitForTransaction(context.Background(), tx.Hash(), 400)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
receipt, err := client.TransactionReceipt(tx.Hash())
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if receipt.Status == gethTypes.ReceiptStatusFailed {
|
|
return errors.New("transaction was not successful, unable to deposit ETH and become a notary")
|
|
}
|
|
|
|
if inPool, err := isAccountInNotaryPool(manager, client.Account()); !inPool || err != nil {
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return errors.New("account has not been able to be deposited in notary pool")
|
|
}
|
|
|
|
log.Infof("Deposited %dETH into contract with transaction hash: %s", new(big.Int).Div(shardparams.DefaultConfig.NotaryDeposit, big.NewInt(params.Ether)), tx.Hash().Hex())
|
|
|
|
return nil
|
|
}
|