Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat : QueryActivatedHeight() #3

Open
wants to merge 4 commits into
base: feat/QueryActivatedHeight
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
96 changes: 53 additions & 43 deletions clientcontroller/evm_consumer.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,7 @@ import (
fpcfg "github.com/babylonchain/finality-provider/finality-provider/config"
"github.com/babylonchain/finality-provider/types"
"github.com/btcsuite/btcd/btcec/v2"
"github.com/ethereum-optimism/optimism/op-bindings/bindings"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/ethclient"
"go.uber.org/zap"
)
Expand All @@ -21,10 +20,10 @@ import (
var _ ConsumerController = &EVMConsumerController{}

type EVMConsumerController struct {
l1Client *ethclient.Client
l2Client *ethclient.Client
cfg *fpcfg.EVMConfig
logger *zap.Logger
l1Client *ethclient.Client
consumerClient *ethclient.Client
cfg *fpcfg.EVMConfig
logger *zap.Logger
}

func NewEVMConsumerController(
Expand All @@ -34,17 +33,17 @@ func NewEVMConsumerController(
if err := evmCfg.Validate(); err != nil {
return nil, fmt.Errorf("invalid config for EVM RPC client: %w", err)
}
l1Client, err := ethclient.Dial(evmCfg.RPCL1Addr)
l1Client, err := ethclient.Dial(evmCfg.L1RPCAddr)
if err != nil {
return nil, fmt.Errorf("failed to connect to the L1 RPC server %s: %w", evmCfg.RPCL1Addr, err)
return nil, fmt.Errorf("failed to connect to the L1 RPC server %s: %w", evmCfg.L1RPCAddr, err)
}
l2Client, err := ethclient.Dial(evmCfg.RPCL2Addr)
consumerClient, err := ethclient.Dial(evmCfg.ConsumerRPCAddr)
if err != nil {
return nil, fmt.Errorf("failed to connect to the L2 RPC server %s: %w", evmCfg.RPCL2Addr, err)
return nil, fmt.Errorf("failed to connect to the Consumer Chain RPC server %s: %w", evmCfg.ConsumerRPCAddr, err)
}
return &EVMConsumerController{
l1Client,
l2Client,
consumerClient,
evmCfg,
logger,
}, nil
Expand All @@ -69,18 +68,7 @@ func (ec *EVMConsumerController) SubmitBatchFinalitySigs(fpPk *btcec.PublicKey,
func (ec *EVMConsumerController) QueryFinalityProviderVotingPower(fpPk *btcec.PublicKey, blockHeight uint64) (uint64, error) {
/* TODO: implement

latest_committed_l2_height = read `latestBlockNumber()` from the L1 L2OutputOracle contract and return the result

if blockHeight > latest_committed_l2_height:

query the VP from the L1 oracle contract using "latest" as the block tag

else:

1. query the L1 event `emit OutputProposed(_outputRoot, nextOutputIndex(), _l2BlockNumber, block.timestamp, block.number);`
to find the first event where the `_l2BlockNumber` >= blockHeight
2. get the block.number from the event
3. query the VP from the L1 oracle contract using `block.number` as the block tag
get votingpower from FP oracle contract

*/

Expand Down Expand Up @@ -132,7 +120,7 @@ func (ec *EVMConsumerController) QueryBlock(height uint64) (*types.BlockInfo, er

number := new(big.Int).SetUint64(height)

header, err := ec.l2Client.HeaderByNumber(context.Background(), number)
header, err := ec.consumerClient.HeaderByNumber(context.Background(), number)
if err != nil {
return nil, fmt.Errorf("failed to get latest block:%s", err)
}
Expand Down Expand Up @@ -164,29 +152,30 @@ func (ec *EVMConsumerController) QueryIsBlockFinalized(height uint64) (bool, err
func (ec *EVMConsumerController) QueryActivatedHeight() (uint64, error) {
/* TODO: implement

oracle_event = query the event in the L1 oracle contract where the FP's voting power is firstly set
oracle_event = query the event in the FP oracle contract where the FP's voting power is firstly set

l1_activated_height = get the L1 block number from the `oracle_event`
l1_activated_height = get the L1 block number from the `oracle_event`

output_event = query the L1 event `emit OutputProposed(_outputRoot, nextOutputIndex(), _l2BlockNumber, block.timestamp, block.number);`
to find the first event where the `block.number` >= l1_activated_height
define votingPower and blockNumber as indexed better for filtering

if output_event == nil:
example : event VotingPowerUpdated(bytes32 bitcoinPublicKey,uint32 chainId,uint64 indexed votingPower, uint256 indexed blockNumber, uint256 blockTimestamp);`

read `nextBlockNumber()` from the L1 L2OutputOracle contract and return the result
read atBlock from L1 EOTSVerifier contract

else:
find the first event where the `atBlock` >= l1_activated_height

return output_event._l2BlockNumber

*/
if output_event == nil:
read `nextBlockNumber()` from the EOTSVerifier contract and return the result
else:
return output_event.atBlock */

return 0, nil

}

func (ec *EVMConsumerController) QueryLatestBlockHeight() (uint64, error) {

header, err := ec.l2Client.HeaderByNumber(context.Background(), nil)
header, err := ec.consumerClient.HeaderByNumber(context.Background(), nil)
if err != nil {
return 0, fmt.Errorf("failed to get latest block:%s", err)
}
Expand All @@ -197,22 +186,43 @@ func (ec *EVMConsumerController) QueryLatestBlockHeight() (uint64, error) {
func (ec *EVMConsumerController) Close() error {

ec.l1Client.Close()
ec.l2Client.Close()
ec.consumerClient.Close()

return nil
}

func (ec *EVMConsumerController) queryLatestFinalizedNumber() (uint64, error) {

output, err := bindings.NewL2OutputOracle(common.HexToAddress(ec.cfg.L2OutputOracleAddr), ec.l1Client)
if err != nil {
return 0, fmt.Errorf("failed to instantiate L2OutputOracle contract:%s ", err)
}
//get latest block number from EOTSVerifier contract
return 0, nil
}

func (ec *EVMConsumerController) querynextBlockNumber() (uint64, error) {

lastNumber, err := output.LatestBlockNumber(nil)
//get next block number from EOTSVerifier contract
return 0, nil
}

func (ec *EVMConsumerController) queryBestBlock(query ethereum.FilterQuery, l1_activated_height *big.Int) (*big.Int, error) {
//to find the first event where the `block.number` >= l1_activated_height
logs, err := ec.l1Client.FilterLogs(context.Background(), query)
if err != nil {
return 0, fmt.Errorf("failed to get latest finalize block number:%s ", err)
return nil, err
}
// Binary search
searchLeft, searchRight := 0, len(logs)-1
var result *big.Int

for searchLeft <= searchRight {
searchMid := searchLeft + (searchRight-searchLeft)/2
blockNumberValue := new(big.Int).SetBytes(logs[searchMid].Topics[3].Bytes())
if blockNumberValue.Cmp(l1_activated_height) >= 0 {
result = blockNumberValue
searchRight = searchMid - 1
} else {
searchLeft = searchMid + 1
}
}

return lastNumber.Uint64(), err
return result, nil
}
18 changes: 9 additions & 9 deletions finality-provider/config/evm.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,24 +10,24 @@ const (
)

type EVMConfig struct {
RPCL1Addr string `long:"rpcl1-address" description:"address of the L1 RPC server to connect to"`
RPCL2Addr string `long:"rpcl2-address" description:"address of the L2 RPC server to connect to"`
L2OutputOracleAddr string `long:"l2outputoracle-address" description:"address of the L2OutputOracle smart contract"`
BSAddr string `long:"bitcoinstacking-address" description:"address of the BitcoinStaking smart contract"`
L1RPCAddr string `long:"rpcl1-address" description:"address of the L1 RPC server to connect to"`
ConsumerRPCAddr string `long:"consumer-chain-address" description:"address of the consumer chain RPC server to connect to"`
EOTSVerifierAddr string `long:"EOTSVerifier-address" description:"address of the EOTSVerifier smart contract"`
FPOracleAddr string `long:"finality-provider-address" description:"address of the finality provider smart contract"`
}

func DefaultEVMConfig() EVMConfig {
return EVMConfig{
RPCL2Addr: defaultEVMRPCAddr,
L1RPCAddr: defaultEVMRPCAddr,
}
}

func (cfg *EVMConfig) Validate() error {
if _, err := url.Parse(cfg.RPCL1Addr); err != nil {
return fmt.Errorf("rpcl1-addr is not correctly formatted: %w", err)
if _, err := url.Parse(cfg.L1RPCAddr); err != nil {
return fmt.Errorf("rpcl1-address is not correctly formatted: %w", err)
}
if _, err := url.Parse(cfg.RPCL2Addr); err != nil {
return fmt.Errorf("rpcl2-addr is not correctly formatted: %w", err)
if _, err := url.Parse(cfg.ConsumerRPCAddr); err != nil {
return fmt.Errorf("consumer-chain-address is not correctly formatted: %w", err)
}
return nil
}