139 lines
3.6 KiB
Go
139 lines
3.6 KiB
Go
// This implements the interface to the standard go-ethereum library.
|
|
|
|
package ethereum
|
|
|
|
import (
|
|
"context"
|
|
|
|
ethereum "github.com/ethereum/go-ethereum"
|
|
ethBind "github.com/ethereum/go-ethereum/accounts/abi/bind"
|
|
ethCommon "github.com/ethereum/go-ethereum/common"
|
|
ethTypes "github.com/ethereum/go-ethereum/core/types"
|
|
ethClient "github.com/ethereum/go-ethereum/ethclient"
|
|
ethEvent "github.com/ethereum/go-ethereum/event"
|
|
|
|
common "github.com/certusone/wormhole/node/pkg/common"
|
|
ethAbi "github.com/certusone/wormhole/node/pkg/ethereum/abi"
|
|
|
|
"go.uber.org/zap"
|
|
)
|
|
|
|
type EthImpl struct {
|
|
NetworkName string
|
|
logger *zap.Logger
|
|
client *ethClient.Client
|
|
filterer *ethAbi.AbiFilterer
|
|
caller *ethAbi.AbiCaller
|
|
}
|
|
|
|
func (e *EthImpl) SetLogger(l *zap.Logger) {
|
|
e.logger = l
|
|
}
|
|
|
|
func (e *EthImpl) DialContext(ctx context.Context, rawurl string) (err error) {
|
|
e.client, err = ethClient.DialContext(ctx, rawurl)
|
|
return
|
|
}
|
|
|
|
func (e *EthImpl) NewAbiFilterer(address ethCommon.Address) (err error) {
|
|
e.filterer, err = ethAbi.NewAbiFilterer(address, e.client)
|
|
return
|
|
}
|
|
|
|
func (e *EthImpl) NewAbiCaller(address ethCommon.Address) (err error) {
|
|
e.caller, err = ethAbi.NewAbiCaller(address, e.client)
|
|
return
|
|
}
|
|
|
|
func (e *EthImpl) GetCurrentGuardianSetIndex(ctx context.Context) (uint32, error) {
|
|
if e.caller == nil {
|
|
panic("caller is not initialized!")
|
|
}
|
|
|
|
opts := ðBind.CallOpts{Context: ctx}
|
|
return e.caller.GetCurrentGuardianSetIndex(opts)
|
|
}
|
|
|
|
func (e *EthImpl) GetGuardianSet(ctx context.Context, index uint32) (ethAbi.StructsGuardianSet, error) {
|
|
if e.caller == nil {
|
|
panic("caller is not initialized!")
|
|
}
|
|
|
|
opts := ðBind.CallOpts{Context: ctx}
|
|
return e.caller.GetGuardianSet(opts, index)
|
|
}
|
|
|
|
func (e *EthImpl) WatchLogMessagePublished(_ctx, timeout context.Context, sink chan<- *ethAbi.AbiLogMessagePublished) (ethEvent.Subscription, error) {
|
|
if e.filterer == nil {
|
|
panic("filterer is not initialized!")
|
|
}
|
|
|
|
return e.filterer.WatchLogMessagePublished(ðBind.WatchOpts{Context: timeout}, sink, nil)
|
|
}
|
|
|
|
func (e *EthImpl) TransactionReceipt(ctx context.Context, txHash ethCommon.Hash) (*ethTypes.Receipt, error) {
|
|
if e.client == nil {
|
|
panic("client is not initialized!")
|
|
}
|
|
|
|
return e.client.TransactionReceipt(ctx, txHash)
|
|
}
|
|
|
|
func (e *EthImpl) TimeOfBlockByHash(ctx context.Context, hash ethCommon.Hash) (uint64, error) {
|
|
if e.client == nil {
|
|
panic("client is not initialized!")
|
|
}
|
|
|
|
block, err := e.client.BlockByHash(ctx, hash)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
|
|
return block.Time(), err
|
|
}
|
|
|
|
func (e *EthImpl) ParseLogMessagePublished(log ethTypes.Log) (*ethAbi.AbiLogMessagePublished, error) {
|
|
if e.filterer == nil {
|
|
panic("filterer is not initialized!")
|
|
}
|
|
|
|
return e.filterer.ParseLogMessagePublished(log)
|
|
}
|
|
|
|
func (e *EthImpl) SubscribeForBlocks(ctx context.Context, sink chan<- *common.NewBlock) (ethereum.Subscription, error) {
|
|
if e.client == nil {
|
|
panic("client is not initialized!")
|
|
}
|
|
|
|
headSink := make(chan *ethTypes.Header, 2)
|
|
headerSubscription, err := e.client.SubscribeNewHead(ctx, headSink)
|
|
if err != nil {
|
|
return headerSubscription, err
|
|
}
|
|
|
|
// The purpose of this is to map events from the geth event channel to the new block event channel.
|
|
go func() {
|
|
for {
|
|
select {
|
|
case <-ctx.Done():
|
|
return
|
|
case ev := <-headSink:
|
|
if ev == nil {
|
|
e.logger.Error("new header event is nil", zap.String("eth_network", e.NetworkName))
|
|
continue
|
|
}
|
|
if ev.Number == nil {
|
|
e.logger.Error("new header block number is nil", zap.String("eth_network", e.NetworkName))
|
|
continue
|
|
}
|
|
sink <- &common.NewBlock{
|
|
Number: ev.Number,
|
|
Hash: ev.Hash(),
|
|
}
|
|
}
|
|
}
|
|
}()
|
|
|
|
return headerSubscription, err
|
|
}
|