code.vegaprotocol.io/vega@v0.79.0/wallet/pkg/send_transaction.go (about)

     1  // Copyright (C) 2023 Gobalsky Labs Limited
     2  //
     3  // This program is free software: you can redistribute it and/or modify
     4  // it under the terms of the GNU Affero General Public License as
     5  // published by the Free Software Foundation, either version 3 of the
     6  // License, or (at your option) any later version.
     7  //
     8  // This program is distributed in the hope that it will be useful,
     9  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    10  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    11  // GNU Affero General Public License for more details.
    12  //
    13  // You should have received a copy of the GNU Affero General Public License
    14  // along with this program.  If not, see <http://www.gnu.org/licenses/>.
    15  
    16  package pkg
    17  
    18  import (
    19  	"context"
    20  	"fmt"
    21  
    22  	"code.vegaprotocol.io/vega/commands"
    23  	vgcrypto "code.vegaprotocol.io/vega/libs/crypto"
    24  	apipb "code.vegaprotocol.io/vega/protos/vega/api/v1"
    25  	commandspb "code.vegaprotocol.io/vega/protos/vega/commands/v1"
    26  	walletpb "code.vegaprotocol.io/vega/protos/vega/wallet/v1"
    27  	"code.vegaprotocol.io/vega/wallet/api"
    28  	wcommands "code.vegaprotocol.io/vega/wallet/commands"
    29  	"code.vegaprotocol.io/vega/wallet/wallet"
    30  )
    31  
    32  type Node interface {
    33  	SendTransaction(context.Context, *commandspb.Transaction, apipb.SubmitTransactionRequest_Type) (*apipb.SubmitTransactionResponse, error)
    34  	LastBlock(context.Context) (*apipb.LastBlockHeightResponse, error)
    35  }
    36  
    37  func SendTransaction(ctx context.Context, w wallet.Wallet, pubKey string, request *walletpb.SubmitTransactionRequest, node Node) (*apipb.SubmitTransactionResponse, error) {
    38  	request.PubKey = pubKey
    39  	request.Propagate = true
    40  	if errs := wcommands.CheckSubmitTransactionRequest(request); !errs.Empty() {
    41  		return nil, errs
    42  	}
    43  
    44  	lastBlockData, err := node.LastBlock(ctx)
    45  	if err != nil {
    46  		return nil, api.ErrCouldNotGetLastBlockInformation
    47  	}
    48  
    49  	marshaledInputData, err := wcommands.ToMarshaledInputData(request, lastBlockData.Height)
    50  	if err != nil {
    51  		return nil, fmt.Errorf("could not marshal the input data: %w", err)
    52  	}
    53  
    54  	signature, err := w.SignTx(pubKey, commands.BundleInputDataForSigning(marshaledInputData, lastBlockData.ChainId))
    55  	if err != nil {
    56  		return nil, fmt.Errorf("could not sign the transaction: %w", err)
    57  	}
    58  
    59  	// Build the transaction.
    60  	tx := commands.NewTransaction(pubKey, marshaledInputData, &commandspb.Signature{
    61  		Value:   signature.Value,
    62  		Algo:    signature.Algo,
    63  		Version: signature.Version,
    64  	})
    65  
    66  	// Generate the proof of work for the transaction.
    67  	txID := vgcrypto.RandomHash()
    68  	powNonce, _, err := vgcrypto.PoW(lastBlockData.Hash, txID, uint(lastBlockData.SpamPowDifficulty), lastBlockData.SpamPowHashFunction)
    69  	if err != nil {
    70  		return nil, fmt.Errorf("could not compute the proof-of-work: %w", err)
    71  	}
    72  
    73  	tx.Pow = &commandspb.ProofOfWork{
    74  		Nonce: powNonce,
    75  		Tid:   txID,
    76  	}
    77  
    78  	result, err := node.SendTransaction(ctx, tx, apipb.SubmitTransactionRequest_TYPE_SYNC)
    79  	if err != nil {
    80  		return nil, err
    81  	}
    82  
    83  	return result, nil
    84  }