github.com/neatlab/neatio@v1.7.3-0.20220425043230-d903e92fcc75/neatcli/neatio.go (about)

     1  package neatcli
     2  
     3  import (
     4  	"context"
     5  	"crypto/ecdsa"
     6  	"math/big"
     7  	"math/rand"
     8  	"time"
     9  
    10  	"github.com/neatlab/neatio/chain/core/types"
    11  	"github.com/neatlab/neatio/chain/log"
    12  	neatAbi "github.com/neatlab/neatio/neatabi/abi"
    13  	"github.com/neatlab/neatio/params"
    14  	"github.com/neatlab/neatio/utilities/common"
    15  	"github.com/neatlab/neatio/utilities/common/hexutil"
    16  	"github.com/neatlab/neatio/utilities/crypto"
    17  	"github.com/pkg/errors"
    18  )
    19  
    20  func (ec *Client) BlockNumber(ctx context.Context) (*big.Int, error) {
    21  
    22  	var hex hexutil.Big
    23  
    24  	err := ec.c.CallContext(ctx, &hex, "eth_blockNumber")
    25  	if err != nil {
    26  		return nil, err
    27  	}
    28  	return (*big.Int)(&hex), nil
    29  }
    30  
    31  func (ec *Client) SendDataToMainChain(ctx context.Context, data []byte, prv *ecdsa.PrivateKey, mainChainId string) (common.Hash, error) {
    32  
    33  	bs, err := neatAbi.ChainABI.Pack(neatAbi.SaveDataToMainChain.String(), data)
    34  	if err != nil {
    35  		return common.Hash{}, err
    36  	}
    37  
    38  	account := crypto.PubkeyToAddress(prv.PublicKey)
    39  
    40  	nonce, err := ec.NonceAt(ctx, account, nil)
    41  	if err != nil {
    42  		return common.Hash{}, err
    43  	}
    44  
    45  	digest := crypto.Keccak256([]byte(mainChainId))
    46  	signer := types.NewEIP155Signer(new(big.Int).SetBytes(digest[:]))
    47  
    48  	var hash = common.Hash{}
    49  
    50  	err = retry(30, time.Second*3, func() error {
    51  
    52  		gasPrice, err := ec.SuggestGasPrice(ctx)
    53  		if err != nil {
    54  			return err
    55  		}
    56  
    57  	SendTX:
    58  
    59  		tx := types.NewTransaction(nonce, neatAbi.NeatioSmartContractAddress, nil, 0, gasPrice, bs)
    60  
    61  		signedTx, err := types.SignTx(tx, signer, prv)
    62  		if err != nil {
    63  			return err
    64  		}
    65  
    66  		err = ec.SendTransaction(ctx, signedTx)
    67  		if err != nil {
    68  			if err.Error() == "nonce too low" {
    69  				log.Warnf("SendDataToMainChain: failed, nonce too low, %v current nonce is %v. Will try to increase the nonce then send again.", account, nonce)
    70  				nonce += 1
    71  				goto SendTX
    72  			} else {
    73  				return err
    74  			}
    75  		}
    76  
    77  		hash = signedTx.Hash()
    78  		return nil
    79  	})
    80  
    81  	return hash, err
    82  }
    83  
    84  func (ec *Client) BroadcastDataToMainChain(ctx context.Context, chainId string, data []byte) error {
    85  	if chainId == "" || chainId == params.MainnetChainConfig.NeatChainId || chainId == params.TestnetChainConfig.NeatChainId {
    86  		return errors.New("invalid side chainId")
    87  	}
    88  
    89  	err := retry(1, time.Millisecond*200, func() error {
    90  		return ec.c.CallContext(ctx, nil, "chain_broadcastTX3ProofData", common.ToHex(data))
    91  	})
    92  
    93  	return err
    94  }
    95  
    96  func retry(attemps int, sleep time.Duration, fn func() error) error {
    97  
    98  	if err := fn(); err != nil {
    99  		if attemps--; attemps >= 0 {
   100  
   101  			jitter := time.Duration(rand.Int63n(int64(sleep)))
   102  			sleep = sleep + jitter/2
   103  
   104  			time.Sleep(sleep)
   105  			return retry(attemps, sleep*2, fn)
   106  		}
   107  
   108  		return err
   109  	}
   110  
   111  	return nil
   112  }