github.com/amazechain/amc@v0.1.3/accounts/external/backend.go (about)

     1  // Copyright 2023 The AmazeChain Authors
     2  // This file is part of the AmazeChain library.
     3  //
     4  // The AmazeChain library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The AmazeChain library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the AmazeChain library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package external
    18  
    19  //import (
    20  //	"fmt"
    21  //	"math/big"
    22  //	"sync"
    23  //
    24  //	"github.com/amazechain/amc/accounts"
    25  //	"github.com/amazechain/amc/common"
    26  //	types2 "github.com/amazechain/amc/common/types"
    27  //	"github.com/amazechain/amc/internal/avm/common/hexutil"
    28  //	"github.com/amazechain/amc/internal/avm/types"
    29  //	"github.com/amazechain/amc/log"
    30  //	event "github.com/amazechain/amc/modules/event/v2"
    31  //	"github.com/amazechain/amc/rpc"
    32  //	"github.com/amazechain/amc/signer/core/apitypes"
    33  //)
    34  //
    35  //type ExternalBackend struct {
    36  //	signers []accounts.Wallet
    37  //}
    38  //
    39  //func (eb *ExternalBackend) Wallets() []accounts.Wallet {
    40  //	return eb.signers
    41  //}
    42  //
    43  //func NewExternalBackend(endpoint string) (*ExternalBackend, error) {
    44  //	signer, err := NewExternalSigner(endpoint)
    45  //	if err != nil {
    46  //		return nil, err
    47  //	}
    48  //	return &ExternalBackend{
    49  //		signers: []accounts.Wallet{signer},
    50  //	}, nil
    51  //}
    52  //
    53  //func (eb *ExternalBackend) Subscribe(sink chan<- accounts.WalletEvent) event.Subscription {
    54  //	return event.NewSubscription(func(quit <-chan struct{}) error {
    55  //		<-quit
    56  //		return nil
    57  //	})
    58  //}
    59  //
    60  //// ExternalSigner provides an API to interact with an external signer (clef)
    61  //// It proxies request to the external signer while forwarding relevant
    62  //// request headers
    63  //type ExternalSigner struct {
    64  //	client   *rpc.Client
    65  //	endpoint string
    66  //	status   string
    67  //	cacheMu  sync.RWMutex
    68  //	cache    []accounts.Account
    69  //}
    70  //
    71  //func NewExternalSigner(endpoint string) (*ExternalSigner, error) {
    72  //	client, err := rpc.Dial(endpoint)
    73  //	if err != nil {
    74  //		return nil, err
    75  //	}
    76  //	extsigner := &ExternalSigner{
    77  //		client:   client,
    78  //		endpoint: endpoint,
    79  //	}
    80  //	// Check if reachable
    81  //	version, err := extsigner.pingVersion()
    82  //	if err != nil {
    83  //		return nil, err
    84  //	}
    85  //	extsigner.status = fmt.Sprintf("ok [version=%v]", version)
    86  //	return extsigner, nil
    87  //}
    88  //
    89  //func (api *ExternalSigner) URL() accounts.URL {
    90  //	return accounts.URL{
    91  //		Scheme: "extapi",
    92  //		Path:   api.endpoint,
    93  //	}
    94  //}
    95  //
    96  //func (api *ExternalSigner) Status() (string, error) {
    97  //	return api.status, nil
    98  //}
    99  //
   100  //func (api *ExternalSigner) Open(passphrase string) error {
   101  //	return fmt.Errorf("operation not supported on external signers")
   102  //}
   103  //
   104  //func (api *ExternalSigner) Close() error {
   105  //	return fmt.Errorf("operation not supported on external signers")
   106  //}
   107  //
   108  //func (api *ExternalSigner) Accounts() []accounts.Account {
   109  //	var accnts []accounts.Account
   110  //	res, err := api.listAccounts()
   111  //	if err != nil {
   112  //		log.Error("account listing failed", "error", err)
   113  //		return accnts
   114  //	}
   115  //	for _, addr := range res {
   116  //		accnts = append(accnts, accounts.Account{
   117  //			URL: accounts.URL{
   118  //				Scheme: "extapi",
   119  //				Path:   api.endpoint,
   120  //			},
   121  //			Address: addr,
   122  //		})
   123  //	}
   124  //	api.cacheMu.Lock()
   125  //	api.cache = accnts
   126  //	api.cacheMu.Unlock()
   127  //	return accnts
   128  //}
   129  //
   130  //func (api *ExternalSigner) Contains(account accounts.Account) bool {
   131  //	api.cacheMu.RLock()
   132  //	defer api.cacheMu.RUnlock()
   133  //	if api.cache == nil {
   134  //		// If we haven't already fetched the accounts, it's time to do so now
   135  //		api.cacheMu.RUnlock()
   136  //		api.Accounts()
   137  //		api.cacheMu.RLock()
   138  //	}
   139  //	for _, a := range api.cache {
   140  //		if a.Address == account.Address && (account.URL == (accounts.URL{}) || account.URL == api.URL()) {
   141  //			return true
   142  //		}
   143  //	}
   144  //	return false
   145  //}
   146  //
   147  //func (api *ExternalSigner) Derive(path accounts.DerivationPath, pin bool) (accounts.Account, error) {
   148  //	return accounts.Account{}, fmt.Errorf("operation not supported on external signers")
   149  //}
   150  //
   151  //func (api *ExternalSigner) SelfDerive(bases []accounts.DerivationPath, chain common.ChainStateReader) {
   152  //	log.Error("operation SelfDerive not supported on external signers")
   153  //}
   154  //
   155  //// SignData signs keccak256(data). The mimetype parameter describes the type of data being signed
   156  //func (api *ExternalSigner) SignData(account accounts.Account, mimeType string, data []byte) ([]byte, error) {
   157  //	var res hexutil.Bytes
   158  //	var signAddress = common.NewMixedcaseAddress(account.Address)
   159  //	if err := api.client.Call(&res, "account_signData",
   160  //		mimeType,
   161  //		&signAddress, // Need to use the pointer here, because of how MarshalJSON is defined
   162  //		hexutil.Encode(data)); err != nil {
   163  //		return nil, err
   164  //	}
   165  //	// If V is on 27/28-form, convert to 0/1 for Clique
   166  //	if mimeType == accounts.MimetypeClique && (res[64] == 27 || res[64] == 28) {
   167  //		res[64] -= 27 // Transform V from 27/28 to 0/1 for Clique use
   168  //	}
   169  //	return res, nil
   170  //}
   171  //
   172  //func (api *ExternalSigner) SignText(account accounts.Account, text []byte) ([]byte, error) {
   173  //	var signature hexutil.Bytes
   174  //	var signAddress = common.NewMixedcaseAddress(account.Address)
   175  //	if err := api.client.Call(&signature, "account_signData",
   176  //		accounts.MimetypeTextPlain,
   177  //		&signAddress, // Need to use the pointer here, because of how MarshalJSON is defined
   178  //		hexutil.Encode(text)); err != nil {
   179  //		return nil, err
   180  //	}
   181  //	if signature[64] == 27 || signature[64] == 28 {
   182  //		// If clef is used as a backend, it may already have transformed
   183  //		// the signature to ethereum-type signature.
   184  //		signature[64] -= 27 // Transform V from Ethereum-legacy to 0/1
   185  //	}
   186  //	return signature, nil
   187  //}
   188  //
   189  //// signTransactionResult represents the signinig result returned by clef.
   190  //type signTransactionResult struct {
   191  //	Raw hexutil.Bytes      `json:"raw"`
   192  //	Tx  *types.Transaction `json:"tx"`
   193  //}
   194  //
   195  //// SignTx sends the transaction to the external signer.
   196  //// If chainID is nil, or tx.ChainID is zero, the chain ID will be assigned
   197  //// by the external signer. For non-legacy transactions, the chain ID of the
   198  //// transaction overrides the chainID parameter.
   199  //func (api *ExternalSigner) SignTx(account accounts.Account, tx *types.Transaction, chainID *big.Int) (*types.Transaction, error) {
   200  //	data := hexutil.Bytes(tx.Data())
   201  //	var to *common.MixedcaseAddress
   202  //	if tx.To() != nil {
   203  //		t := common.NewMixedcaseAddress(*tx.To())
   204  //		to = &t
   205  //	}
   206  //	args := &apitypes.SendTxArgs{
   207  //		Data:  &data,
   208  //		Nonce: hexutil.Uint64(tx.Nonce()),
   209  //		Value: hexutil.Big(*tx.Value()),
   210  //		Gas:   hexutil.Uint64(tx.Gas()),
   211  //		To:    to,
   212  //		From:  common.NewMixedcaseAddress(account.Address),
   213  //	}
   214  //	switch tx.Type() {
   215  //	case types.LegacyTxType, types.AccessListTxType:
   216  //		args.GasPrice = (*hexutil.Big)(tx.GasPrice())
   217  //	case types.DynamicFeeTxType:
   218  //		args.MaxFeePerGas = (*hexutil.Big)(tx.GasFeeCap())
   219  //		args.MaxPriorityFeePerGas = (*hexutil.Big)(tx.GasTipCap())
   220  //	default:
   221  //		return nil, fmt.Errorf("unsupported tx type %d", tx.Type())
   222  //	}
   223  //	// We should request the default chain id that we're operating with
   224  //	// (the chain we're executing on)
   225  //	if chainID != nil && chainID.Sign() != 0 {
   226  //		args.ChainID = (*hexutil.Big)(chainID)
   227  //	}
   228  //	if tx.Type() != types.LegacyTxType {
   229  //		// However, if the user asked for a particular chain id, then we should
   230  //		// use that instead.
   231  //		if tx.ChainId().Sign() != 0 {
   232  //			args.ChainID = (*hexutil.Big)(tx.ChainId())
   233  //		}
   234  //		accessList := tx.AccessList()
   235  //		args.AccessList = &accessList
   236  //	}
   237  //	var res signTransactionResult
   238  //	if err := api.client.Call(&res, "account_signTransaction", args); err != nil {
   239  //		return nil, err
   240  //	}
   241  //	return res.Tx, nil
   242  //}
   243  //
   244  //func (api *ExternalSigner) SignTextWithPassphrase(account accounts.Account, passphrase string, text []byte) ([]byte, error) {
   245  //	return []byte{}, fmt.Errorf("password-operations not supported on external signers")
   246  //}
   247  //
   248  //func (api *ExternalSigner) SignTxWithPassphrase(account accounts.Account, passphrase string, tx *types.Transaction, chainID *big.Int) (*types.Transaction, error) {
   249  //	return nil, fmt.Errorf("password-operations not supported on external signers")
   250  //}
   251  //func (api *ExternalSigner) SignDataWithPassphrase(account accounts.Account, passphrase, mimeType string, data []byte) ([]byte, error) {
   252  //	return nil, fmt.Errorf("password-operations not supported on external signers")
   253  //}
   254  //
   255  //func (api *ExternalSigner) listAccounts() ([]types2.Address, error) {
   256  //	var res []types2.Address
   257  //	if err := api.client.Call(&res, "account_list"); err != nil {
   258  //		return nil, err
   259  //	}
   260  //	return res, nil
   261  //}
   262  //
   263  //func (api *ExternalSigner) pingVersion() (string, error) {
   264  //	var v string
   265  //	if err := api.client.Call(&v, "account_version"); err != nil {
   266  //		return "", err
   267  //	}
   268  //	return v, nil
   269  //}