Skip to content

Commit

Permalink
feat: Convert all assets to be associated to the configured Ethereum …
Browse files Browse the repository at this point in the history
…chain
  • Loading branch information
ValentinTrinque committed Feb 27, 2024
1 parent 36b665c commit 59d4aea
Show file tree
Hide file tree
Showing 15 changed files with 337 additions and 287 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,7 @@
- [10517](https://github.com/vegaprotocol/vega/issues/10517) - Add optional cap to metric based rewards.
- [10246](https://github.com/vegaprotocol/vega/issues/10246) - Add quantum volumes to teams statistics API.
- [10550](https://github.com/vegaprotocol/vega/issues/10550) - Update network parameters with default values.
- [10612](https://github.com/vegaprotocol/vega/issues/10612) - Convert all assets to be associated to the configured Ethereum chain.

### 🐛 Fixes

Expand Down
6 changes: 3 additions & 3 deletions core/assets/assets.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,12 @@ import (
)

var (
ErrAssetInvalid = errors.New("asset invalid")
ErrAssetDoesNotExist = errors.New("asset does not exist")
ErrUnknownAssetSource = errors.New("unknown asset source")
)

//go:generate go run github.com/golang/mock/mockgen -destination mocks/mocks.go -package mocks code.vegaprotocol.io/vega/core/assets ERC20BridgeView,Notary

type ERC20BridgeView interface {
FindAsset(asset *types.AssetDetails) error
}
Expand Down Expand Up @@ -261,12 +261,12 @@ func (s *Service) assetFromDetails(assetID string, assetDetails *types.AssetDeta
builtin.New(assetID, assetDetails),
}, nil
case *types.AssetDetailsErc20:
// TODO(): fix once the ethereum wallet and client are not required
// anymore to construct assets
var (
asset *erc20.ERC20
err error
)
// TODO(): fix once the ethereum wallet and client are not required
// anymore to construct assets
if s.isValidator {
asset, err = erc20.New(assetID, assetDetails, s.ethWallet, s.ethClient)
} else {
Expand Down
12 changes: 4 additions & 8 deletions core/assets/erc20/erc20.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,7 @@ import (
ethtypes "github.com/ethereum/go-ethereum/core/types"
)

var (
ErrUnableToFindDeposit = errors.New("unable to find erc20 deposit event")
ErrUnableToFindWithdrawal = errors.New("unable to find erc20 withdrawal event")
ErrUnableToFindERC20AssetList = errors.New("unable to find erc20 asset list event")
ErrUnableToFindERC20AssetLimitsUpdated = errors.New("unable to find ERC20 asset limits updated event")
ErrMissingConfirmations = errors.New("missing confirmation from ethereum")
ErrNotAnErc20Asset = errors.New("not an erc20 asset")
)
var ErrNotAnErc20Asset = errors.New("not an erc20 asset")

//go:generate go run github.com/golang/mock/mockgen -destination mocks/eth_client_mock.go -package mocks code.vegaprotocol.io/vega/core/assets/erc20 ETHClient
type ETHClient interface {
Expand All @@ -51,11 +44,13 @@ type ETHClient interface {
CollateralBridgeAddress() ethcommon.Address
CurrentHeight(context.Context) (uint64, error)
ConfirmationsRequired() uint64
ConfiguredChainID() string
}

type ERC20 struct {
asset *types.Asset
address string
chainID string
ok bool
wallet ethnw.EthereumWallet
ethClient ETHClient
Expand All @@ -78,6 +73,7 @@ func New(
Details: asset,
Status: types.AssetStatusProposed,
},
chainID: source.ChainID,
address: source.ContractAddress,
wallet: w,
ethClient: ethClient,
Expand Down
4 changes: 4 additions & 0 deletions core/assets/erc20/erc20_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,10 @@ type testEthClient struct {
bind.ContractBackend
}

func (testEthClient) ConfiguredChainID() string {
return "1"
}

func (testEthClient) HeaderByNumber(context.Context, *big.Int) (*ethtypes.Header, error) {
return nil, nil
}
Expand Down
14 changes: 14 additions & 0 deletions core/assets/erc20/mocks/eth_client_mock.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

26 changes: 23 additions & 3 deletions core/assets/snapshot.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@ package assets
import (
"context"

"code.vegaprotocol.io/vega/core/events"
"code.vegaprotocol.io/vega/core/types"
vgcontext "code.vegaprotocol.io/vega/libs/context"
"code.vegaprotocol.io/vega/libs/proto"
)

Expand Down Expand Up @@ -99,7 +101,6 @@ func (s *Service) serialiseK(serialFunc func() ([]byte, error), dataField *[]byt
return data, nil
}

// get the serialised form and hash of the given key.
func (s *Service) serialise(k string) ([]byte, error) {
switch k {
case activeKey:
Expand All @@ -122,7 +123,7 @@ func (s *Service) LoadState(ctx context.Context, p *types.Payload) ([]types.Stat
if s.Namespace() != p.Data.Namespace() {
return nil, types.ErrInvalidSnapshotNamespace
}
// see what we're reloading

switch pl := p.Data.(type) {
case *types.PayloadActiveAssets:
return nil, s.restoreActive(ctx, pl.ActiveAssets, p)
Expand All @@ -139,6 +140,8 @@ func (s *Service) restoreActive(ctx context.Context, active *types.ActiveAssets,
var err error
s.assets = map[string]*Asset{}
for _, p := range active.Assets {
s.applyMigrations(ctx, p)

if _, err = s.NewAsset(ctx, p.ID, p.Details); err != nil {
return err
}
Expand All @@ -165,6 +168,8 @@ func (s *Service) restorePending(ctx context.Context, pending *types.PendingAsse
var err error
s.pendingAssets = map[string]*Asset{}
for _, p := range pending.Assets {
s.applyMigrations(ctx, p)

assetID, err := s.NewAsset(ctx, p.ID, p.Details)
if err != nil {
return err
Expand All @@ -180,10 +185,12 @@ func (s *Service) restorePending(ctx context.Context, pending *types.PendingAsse
return err
}

func (s *Service) restorePendingUpdates(_ context.Context, pending *types.PendingAssetUpdates, p *types.Payload) error {
func (s *Service) restorePendingUpdates(ctx context.Context, pending *types.PendingAssetUpdates, p *types.Payload) error {
var err error
s.pendingAssetUpdates = map[string]*Asset{}
for _, p := range pending.Assets {
s.applyMigrations(ctx, p)

if err = s.StageAssetUpdate(p); err != nil {
return err
}
Expand All @@ -192,3 +199,16 @@ func (s *Service) restorePendingUpdates(_ context.Context, pending *types.Pendin

return err
}

func (s *Service) applyMigrations(ctx context.Context, p *types.Asset) {
if vgcontext.InProgressUpgradeFrom(ctx, "v0.74.0") {
// Prior the introduction of the second bridge, existing assets did not track
// the chain ID they originated from. So, when loaded, assets without a chain
// ID are automatically considered to originate from Ethereum Mainnet.
if erc20 := p.Details.GetERC20(); erc20 != nil && erc20.ChainID == "" {
erc20.ChainID = s.ethClient.ConfiguredChainID()
// Ensure the assets are updated in the data-node.
s.broker.Send(events.NewAssetEvent(ctx, *p))
}
}
}
36 changes: 9 additions & 27 deletions core/client/eth/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,17 +70,21 @@ func Dial(ctx context.Context, cfg Config) (*Client, error) {
return &Client{ETHClient: newEthClientWrapper(ethClient), cfg: cfg}, nil
}

func (c *Client) UpdateEthereumConfig(ethConfig *types.EthereumConfig) error {
func (c *Client) ConfiguredChainID() string {
return c.ethConfig.ChainID()
}

func (c *Client) UpdateEthereumConfig(ctx context.Context, ethConfig *types.EthereumConfig) error {
if c == nil {
return nil
}

netID, err := c.NetworkID(context.Background())
netID, err := c.NetworkID(ctx)
if err != nil {
return fmt.Errorf("couldn't retrieve the network ID form the ethereum client: %w", err)
}

chainID, err := c.ChainID(context.Background())
chainID, err := c.ChainID(ctx)
if err != nil {
return fmt.Errorf("couldn't retrieve the chain ID form the ethereum client: %w", err)
}
Expand All @@ -93,19 +97,11 @@ func (c *Client) UpdateEthereumConfig(ethConfig *types.EthereumConfig) error {
return fmt.Errorf("updated chain ID does not matchthe one set during start up, expected %v got %v", ethConfig.ChainID(), chainID)
}

// if err := c.verifyStakingContract(context.Background(), ethConfig); err != nil {
// return fmt.Errorf("failed to verify staking bridge contract: %w", err)
// }

// if err := c.verifyVestingContract(context.Background(), ethConfig); err != nil {
// return fmt.Errorf("failed to verify vesting bridge contract: %w", err)
// }

if err := c.verifyCollateralContract(context.Background(), ethConfig); err != nil {
if err := c.verifyCollateralContract(ctx, ethConfig); err != nil {
return fmt.Errorf("failed to verify collateral bridge contract: %w", err)
}

if err := c.verifyMultisigContract(context.Background(), ethConfig); err != nil {
if err := c.verifyMultisigContract(ctx, ethConfig); err != nil {
return fmt.Errorf("failed to verify multisig control contract: %w", err)
}

Expand Down Expand Up @@ -172,20 +168,6 @@ func (c *Client) VerifyContract(ctx context.Context, address ethcommon.Address,
return nil
}

// func (c *Client) verifyStakingContract(ctx context.Context, ethConfig *types.EthereumConfig) error {
// if address := ethConfig.StakingBridge(); address.HasAddress() {
// return c.VerifyContract(ctx, address.Address(), ContractHashes["staking"])
// }
// return nil
// }

// func (c *Client) verifyVestingContract(ctx context.Context, ethConfig *types.EthereumConfig) error {
// if address := ethConfig.VestingBridge(); address.HasAddress() {
// return c.VerifyContract(ctx, address.Address(), ContractHashes["vesting"])
// }
// return nil
// }

func (c *Client) verifyCollateralContract(ctx context.Context, ethConfig *types.EthereumConfig) error {
if address := ethConfig.CollateralBridge(); address.HasAddress() {
return c.VerifyContract(ctx, address.Address(), ContractHashes["collateral"])
Expand Down
4 changes: 2 additions & 2 deletions core/datasource/external/ethcall/engine.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ func NewEngine(log *logging.Logger, cfg Config, isValidator bool, client EthRead
}

// EnsureChainID tells the engine which chainID it should be related to, and it confirms this against the its client.
func (e *Engine) EnsureChainID(chainID string, blockInterval uint64, confirmWithClient bool) {
func (e *Engine) EnsureChainID(ctx context.Context, chainID string, blockInterval uint64, confirmWithClient bool) {
chainIDU, _ := strconv.ParseUint(chainID, 10, 64)
e.chainID.Store(chainIDU)
e.blockInterval.Store(blockInterval)
Expand All @@ -110,7 +110,7 @@ func (e *Engine) EnsureChainID(chainID string, blockInterval uint64, confirmWith

// if the node is a validator, we now check the chainID against the chain the client is connected to.
if confirmWithClient {
cid, err := e.client.ChainID(context.Background())
cid, err := e.client.ChainID(ctx)
if err != nil {
log.Panic("could not load chain ID", logging.Error(err))
}
Expand Down
8 changes: 4 additions & 4 deletions core/protocol/all_services.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ type EthCallEngine interface {
GetInitialTriggerTime(id string) (uint64, error)
OnSpecActivated(ctx context.Context, spec datasource.Spec) error
OnSpecDeactivated(ctx context.Context, spec datasource.Spec)
EnsureChainID(chainID string, blockInterval uint64, confirmWithClient bool)
EnsureChainID(ctx context.Context, chainID string, blockInterval uint64, confirmWithClient bool)
}

type allServices struct {
Expand Down Expand Up @@ -680,7 +680,7 @@ func (svcs *allServices) setupNetParameters(powWatchers []netparams.WatchParam)
return fmt.Errorf("invalid Ethereum configuration: %w", err)
}

if err := svcs.ethClient.UpdateEthereumConfig(ethCfg); err != nil {
if err := svcs.ethClient.UpdateEthereumConfig(ctx, ethCfg); err != nil {
return err
}

Expand Down Expand Up @@ -859,14 +859,14 @@ func (svcs *allServices) setupNetParameters(powWatchers []netparams.WatchParam)
},
{
Param: netparams.BlockchainsEthereumConfig,
Watcher: func(_ context.Context, cfg interface{}) error {
Watcher: func(ctx context.Context, cfg interface{}) error {
ethCfg, err := types.EthereumConfigFromUntypedProto(cfg)
if err != nil {
return fmt.Errorf("invalid ethereum configuration: %w", err)
}

// every 1 block for the main ethereum chain is acceptable
svcs.ethCallEngine.EnsureChainID(ethCfg.ChainID(), 1, svcs.conf.HaveEthClient())
svcs.ethCallEngine.EnsureChainID(ctx, ethCfg.ChainID(), 1, svcs.conf.HaveEthClient())

// nothing to do if not a validator
if !svcs.conf.HaveEthClient() {
Expand Down
2 changes: 1 addition & 1 deletion core/protocol/l2_eth_call_engines.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ func (v *L2EthCallEngines) OnEthereumL2ConfigsUpdated(
}

e := ethcall.NewEngine(v.log, v.cfg, v.isValidator, clt, v.forwarder)
e.EnsureChainID(c.ChainID, c.BlockInterval, v.isValidator)
e.EnsureChainID(ctx, c.ChainID, c.BlockInterval, v.isValidator)
v.engines[c.ChainID] = e

// if we are restoring from a snapshot we want to delay starting the engine
Expand Down
Loading

0 comments on commit 59d4aea

Please sign in to comment.