[#496] morph/client: provide notary options on client creation

Signed-off-by: Evgenii Stratonikov <evgeniy@nspcc.ru>
This commit is contained in:
Evgenii Stratonikov 2021-06-01 12:29:32 +03:00 committed by Alex Vanin
parent 7cf0093012
commit 458fc4f5ae
5 changed files with 68 additions and 46 deletions

View file

@ -327,19 +327,17 @@ func New(ctx context.Context, log *zap.Logger, cfg *viper.Viper) (*Server, error
return nil, err return nil, err
} }
// create morph client // enable notary support in the client
server.morphClient, err = createClient(ctx, morphChain) var morphNotaryOpts []client.NotaryOption
if err != nil { if !server.sideNotaryConfig.disabled {
return nil, err morphNotaryOpts = append(morphNotaryOpts, client.WithProxyContract(server.contracts.proxy))
} }
// enable notary support in the client // create morph client
if !server.sideNotaryConfig.disabled { server.morphClient, err = createClient(ctx, morphChain, morphNotaryOpts...)
err = server.morphClient.EnableNotarySupport(server.contracts.proxy)
if err != nil { if err != nil {
return nil, err return nil, err
} }
}
withoutMainNet := cfg.GetBool("without_mainnet") withoutMainNet := cfg.GetBool("without_mainnet")
@ -359,23 +357,20 @@ func New(ctx context.Context, log *zap.Logger, cfg *viper.Viper) (*Server, error
return nil, err return nil, err
} }
// create mainnet client // enable notary support in the client
server.mainnetClient, err = createClient(ctx, mainnetChain) var mainnetNotaryOpts []client.NotaryOption
if err != nil { if !server.mainNotaryConfig.disabled {
return nil, err mainnetNotaryOpts = append(mainnetNotaryOpts,
client.WithProxyContract(server.contracts.processing),
client.WithAlphabetSource(server.morphClient.Committee))
} }
// enable notary support in the client // create mainnet client
if !server.mainNotaryConfig.disabled { server.mainnetClient, err = createClient(ctx, mainnetChain, mainnetNotaryOpts...)
err = server.mainnetClient.EnableNotarySupport(
server.contracts.processing,
client.WithAlphabetSource(server.morphClient.Committee),
)
if err != nil { if err != nil {
return nil, err return nil, err
} }
} }
}
server.pubKey = server.key.PublicKey().Bytes() server.pubKey = server.key.PublicKey().Bytes()
@ -392,7 +387,7 @@ func New(ctx context.Context, log *zap.Logger, cfg *viper.Viper) (*Server, error
fee := server.feeConfig.SideChainFee() fee := server.feeConfig.SideChainFee()
server.auditClient, err = auditWrapper.NewFromMorph(server.morphClient, server.contracts.audit, fee) server.auditClient, err = auditWrapper.NewFromMorph(server.morphClient, server.contracts.audit, fee, client.TryNotary())
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -402,7 +397,7 @@ func New(ctx context.Context, log *zap.Logger, cfg *viper.Viper) (*Server, error
return nil, err return nil, err
} }
server.netmapClient, err = nmWrapper.NewFromMorph(server.morphClient, server.contracts.netmap, fee) server.netmapClient, err = nmWrapper.NewFromMorph(server.morphClient, server.contracts.netmap, fee, client.TryNotary())
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -811,13 +806,14 @@ func createListener(ctx context.Context, p *chainParams) (event.Listener, error)
return listener, err return listener, err
} }
func createClient(ctx context.Context, p *chainParams) (*client.Client, error) { func createClient(ctx context.Context, p *chainParams, notaryOpts ...client.NotaryOption) (*client.Client, error) {
return client.New( return client.New(
p.key, p.key,
p.cfg.GetString(p.name+".endpoint.client"), p.cfg.GetString(p.name+".endpoint.client"),
client.WithContext(ctx), client.WithContext(ctx),
client.WithLogger(p.log), client.WithLogger(p.log),
client.WithDialTimeout(p.cfg.GetDuration(p.name+".dial_timeout")), client.WithDialTimeout(p.cfg.GetDuration(p.name+".dial_timeout")),
client.WithNotaryOptions(notaryOpts...),
) )
} }

View file

@ -12,8 +12,8 @@ import (
type ClientWrapper audit.Client type ClientWrapper audit.Client
// NewFromMorph returns the wrapper instance from the raw morph client. // NewFromMorph returns the wrapper instance from the raw morph client.
func NewFromMorph(cli *client.Client, contract util.Uint160, fee fixedn.Fixed8) (*ClientWrapper, error) { func NewFromMorph(cli *client.Client, contract util.Uint160, fee fixedn.Fixed8, opts ...client.StaticClientOption) (*ClientWrapper, error) {
staticClient, err := client.NewStatic(cli, contract, fee) staticClient, err := client.NewStatic(cli, contract, fee, opts...)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View file

@ -2,6 +2,7 @@ package client
import ( import (
"context" "context"
"fmt"
"time" "time"
"github.com/nspcc-dev/neo-go/pkg/core/native/nativenames" "github.com/nspcc-dev/neo-go/pkg/core/native/nativenames"
@ -27,6 +28,8 @@ type cfg struct {
gas util.Uint160 // native gas script-hash gas util.Uint160 // native gas script-hash
waitInterval time.Duration waitInterval time.Duration
notaryOpts []NotaryOption
} }
const ( const (
@ -93,14 +96,22 @@ func New(key *keys.PrivateKey, endpoint string, opts ...Option) (*Client, error)
return nil, err return nil, err
} }
return &Client{ c := &Client{
logger: cfg.logger, logger: cfg.logger,
client: cli, client: cli,
acc: account, acc: account,
gas: gas, gas: gas,
designate: designate, designate: designate,
waitInterval: cfg.waitInterval, waitInterval: cfg.waitInterval,
}, nil }
if len(cfg.notaryOpts) != 0 {
if err := c.enableNotarySupport(cfg.notaryOpts...); err != nil {
return nil, fmt.Errorf("can't enable notary support: %w", err)
}
}
return c, nil
} }
// WithContext returns a client constructor option that // WithContext returns a client constructor option that
@ -144,3 +155,10 @@ func WithLogger(logger *logger.Logger) Option {
} }
} }
} }
// WithNotaryOptions enables notary support and sets notary options for the client.
func WithNotaryOptions(opts ...NotaryOption) Option {
return func(c *cfg) {
c.notaryOpts = opts
}
}

View file

@ -23,8 +23,8 @@ type Wrapper struct {
} }
// NewFromMorph returns the wrapper instance from the raw morph client. // NewFromMorph returns the wrapper instance from the raw morph client.
func NewFromMorph(cli *client.Client, contract util.Uint160, fee fixedn.Fixed8) (*Wrapper, error) { func NewFromMorph(cli *client.Client, contract util.Uint160, fee fixedn.Fixed8, opts ...client.StaticClientOption) (*Wrapper, error) {
staticClient, err := client.NewStatic(cli, contract, fee) staticClient, err := client.NewStatic(cli, contract, fee, opts...)
if err != nil { if err != nil {
return nil, fmt.Errorf("can't create netmap static client: %w", err) return nil, fmt.Errorf("can't create netmap static client: %w", err)
} }

View file

@ -31,6 +31,8 @@ type (
} }
notaryCfg struct { notaryCfg struct {
proxy util.Uint160
txValidTime, roundTime, fallbackTime uint32 txValidTime, roundTime, fallbackTime uint32
alphabetSource AlphabetKeys alphabetSource AlphabetKeys
@ -63,10 +65,10 @@ func defaultNotaryConfig(c *Client) *notaryCfg {
} }
} }
// EnableNotarySupport creates notary structure in client that provides // enableNotarySupport creates notary structure in client that provides
// ability for client to get alphabet keys from committee or provided source // ability for client to get alphabet keys from committee or provided source
// and use proxy contract script hash to create tx for notary contract. // and use proxy contract script hash to create tx for notary contract.
func (c *Client) EnableNotarySupport(proxy util.Uint160, opts ...NotaryOption) error { func (c *Client) enableNotarySupport(opts ...NotaryOption) error {
cfg := defaultNotaryConfig(c) cfg := defaultNotaryConfig(c)
for _, opt := range opts { for _, opt := range opts {
@ -78,9 +80,13 @@ func (c *Client) EnableNotarySupport(proxy util.Uint160, opts ...NotaryOption) e
return fmt.Errorf("can't get notary contract script hash: %w", err) return fmt.Errorf("can't get notary contract script hash: %w", err)
} }
if cfg.proxy.Equals(util.Uint160{}) {
return errors.New("proxy contract hash is missing")
}
c.notary = &notary{ c.notary = &notary{
notary: notaryContract, notary: notaryContract,
proxy: proxy, proxy: cfg.proxy,
txValidTime: cfg.txValidTime, txValidTime: cfg.txValidTime,
roundTime: cfg.roundTime, roundTime: cfg.roundTime,
fallbackTime: cfg.fallbackTime, fallbackTime: cfg.fallbackTime,
@ -91,7 +97,7 @@ func (c *Client) EnableNotarySupport(proxy util.Uint160, opts ...NotaryOption) e
} }
// NotaryEnabled returns true if notary support was enabled in this instance // NotaryEnabled returns true if notary support was enabled in this instance
// of client by calling `EnableNotarySupport()`. Otherwise returns false. // of client by providing notary options on client creation. Otherwise returns false.
func (c *Client) NotaryEnabled() bool { func (c *Client) NotaryEnabled() bool {
return c.notary != nil return c.notary != nil
} }
@ -102,8 +108,7 @@ func (c *Client) NotaryEnabled() bool {
// be called periodically. Notary support should be enabled in client to // be called periodically. Notary support should be enabled in client to
// use this function. // use this function.
// //
// This function must be invoked after `EnableNotarySupport()` otherwise it // This function must be invoked with notary enabled otherwise it throws panic.
// throws panic.
func (c *Client) DepositNotary(amount fixedn.Fixed8, delta uint32) (util.Uint256, error) { func (c *Client) DepositNotary(amount fixedn.Fixed8, delta uint32) (util.Uint256, error) {
if c.notary == nil { if c.notary == nil {
panic(notaryNotEnabledPanicMsg) panic(notaryNotEnabledPanicMsg)
@ -138,8 +143,7 @@ func (c *Client) DepositNotary(amount fixedn.Fixed8, delta uint32) (util.Uint256
// GetNotaryDeposit returns deposit of client's account in notary contract. // GetNotaryDeposit returns deposit of client's account in notary contract.
// Notary support should be enabled in client to use this function. // Notary support should be enabled in client to use this function.
// //
// This function must be invoked after `EnableNotarySupport()` otherwise it // This function must be invoked with notary enabled otherwise it throws panic.
// throws panic.
func (c *Client) GetNotaryDeposit() (int64, error) { func (c *Client) GetNotaryDeposit() (int64, error) {
if c.notary == nil { if c.notary == nil {
panic(notaryNotEnabledPanicMsg) panic(notaryNotEnabledPanicMsg)
@ -167,8 +171,7 @@ func (c *Client) GetNotaryDeposit() (int64, error) {
// UpdateNotaryList updates list of notary nodes in designate contract. Requires // UpdateNotaryList updates list of notary nodes in designate contract. Requires
// committee multi signature. // committee multi signature.
// //
// This function must be invoked after `EnableNotarySupport()` otherwise it // This function must be invoked with notary enabled otherwise it throws panic.
// throws panic.
func (c *Client) UpdateNotaryList(list keys.PublicKeys) error { func (c *Client) UpdateNotaryList(list keys.PublicKeys) error {
if c.notary == nil { if c.notary == nil {
panic(notaryNotEnabledPanicMsg) panic(notaryNotEnabledPanicMsg)
@ -185,8 +188,7 @@ func (c *Client) UpdateNotaryList(list keys.PublicKeys) error {
// As for side chain list should contain all inner ring nodes. // As for side chain list should contain all inner ring nodes.
// Requires committee multi signature. // Requires committee multi signature.
// //
// This function must be invoked after `EnableNotarySupport()` otherwise it // This function must be invoked with notary enabled otherwise it throws panic.
// throws panic.
func (c *Client) UpdateNeoFSAlphabetList(list keys.PublicKeys) error { func (c *Client) UpdateNeoFSAlphabetList(list keys.PublicKeys) error {
if c.notary == nil { if c.notary == nil {
panic(notaryNotEnabledPanicMsg) panic(notaryNotEnabledPanicMsg)
@ -203,8 +205,7 @@ func (c *Client) UpdateNeoFSAlphabetList(list keys.PublicKeys) error {
// blockchain. Fallback tx is a `RET`. If Notary support is not enabled // blockchain. Fallback tx is a `RET`. If Notary support is not enabled
// it fallbacks to a simple `Invoke()`. // it fallbacks to a simple `Invoke()`.
// //
// This function must be invoked after `EnableNotarySupport()` otherwise it // This function must be invoked with notary enabled otherwise it throws panic.
// throws panic.
func (c *Client) NotaryInvoke(contract util.Uint160, fee fixedn.Fixed8, method string, args ...interface{}) error { func (c *Client) NotaryInvoke(contract util.Uint160, fee fixedn.Fixed8, method string, args ...interface{}) error {
if c.notary == nil { if c.notary == nil {
return c.Invoke(contract, fee, method, args...) return c.Invoke(contract, fee, method, args...)
@ -497,6 +498,13 @@ func WithAlphabetSource(t AlphabetKeys) NotaryOption {
} }
} }
// WithProxyContract sets proxy contract hash.
func WithProxyContract(h util.Uint160) NotaryOption {
return func(c *notaryCfg) {
c.proxy = h
}
}
const alreadyOnChainErrorMessage = "already on chain" const alreadyOnChainErrorMessage = "already on chain"
// Neo RPC node can return `core.ErrInvalidAttribute` error with // Neo RPC node can return `core.ErrInvalidAttribute` error with