mirror of
https://github.com/kaspanet/kaspad.git
synced 2025-06-23 22:42:32 +00:00
[NOD-201] Create AddSubnetwork cli tool (#319)
* [NOD-201] Implemented the AddSubnetwork CLI tool. * [NOD-201] Fixed various bugs in AddSubnetwork. * [NOD-201] Fixed mempool maybeAcceptTransaction verifying gasLimit for a subnetwork registry transaction. * [NOD-201] Fixed serialization/deserialization bugs in addrIndex. * [NOD-201] Fixed BlockConfirmationsByHash not handling the zeroHash. * [NOD-201] Used btclog instead of go log. * [NOD-201] Made gasLimit a command-line flag. Made waitForSubnetworkToBecomeAccepted only return an error. * [NOD-201] Filtered out mempool transactions. * [NOD-201] Fixed embarrassing typos. * [NOD-201] Added subnetwork registry tx fee + appropriate cli flag. * [NOD-201] Skipped TXOs that can't pay for registration.
This commit is contained in:
parent
901bde1fd4
commit
84970a8378
@ -1195,6 +1195,10 @@ func (dag *BlockDAG) GetUTXOEntry(outPoint wire.OutPoint) (*UTXOEntry, bool) {
|
|||||||
// BlockConfirmationsByHash returns the confirmations number for a block with the
|
// BlockConfirmationsByHash returns the confirmations number for a block with the
|
||||||
// given hash. See blockConfirmations for further details.
|
// given hash. See blockConfirmations for further details.
|
||||||
func (dag *BlockDAG) BlockConfirmationsByHash(hash *daghash.Hash) (uint64, error) {
|
func (dag *BlockDAG) BlockConfirmationsByHash(hash *daghash.Hash) (uint64, error) {
|
||||||
|
if hash.IsEqual(&daghash.ZeroHash) {
|
||||||
|
return 0, nil
|
||||||
|
}
|
||||||
|
|
||||||
node := dag.index.LookupNode(hash)
|
node := dag.index.LookupNode(hash)
|
||||||
if node == nil {
|
if node == nil {
|
||||||
return 0, fmt.Errorf("block %s is unknown", hash)
|
return 0, fmt.Errorf("block %s is unknown", hash)
|
||||||
|
@ -134,8 +134,8 @@ func serializeAddrIndexEntry(blockID uint64, txLoc wire.TxLoc) []byte {
|
|||||||
// Serialize the entry.
|
// Serialize the entry.
|
||||||
serialized := make([]byte, 16)
|
serialized := make([]byte, 16)
|
||||||
byteOrder.PutUint64(serialized, blockID)
|
byteOrder.PutUint64(serialized, blockID)
|
||||||
byteOrder.PutUint32(serialized[4:], uint32(txLoc.TxStart))
|
byteOrder.PutUint32(serialized[8:], uint32(txLoc.TxStart))
|
||||||
byteOrder.PutUint32(serialized[8:], uint32(txLoc.TxLen))
|
byteOrder.PutUint32(serialized[12:], uint32(txLoc.TxLen))
|
||||||
return serialized
|
return serialized
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -155,7 +155,7 @@ func deserializeAddrIndexEntry(serialized []byte, region *database.BlockRegion,
|
|||||||
}
|
}
|
||||||
region.Hash = hash
|
region.Hash = hash
|
||||||
region.Offset = byteOrder.Uint32(serialized[8:12])
|
region.Offset = byteOrder.Uint32(serialized[8:12])
|
||||||
region.Len = byteOrder.Uint32(serialized[12:14])
|
region.Len = byteOrder.Uint32(serialized[12:16])
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
87
cmd/addsubnetwork/addsubnetwork.go
Normal file
87
cmd/addsubnetwork/addsubnetwork.go
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/daglabs/btcd/blockdag"
|
||||||
|
"github.com/daglabs/btcd/btcjson"
|
||||||
|
"github.com/daglabs/btcd/rpcclient"
|
||||||
|
"github.com/daglabs/btcd/util/subnetworkid"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
getSubnetworkRetryDelay = 5 * time.Second
|
||||||
|
maxGetSubnetworkRetries = 12
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
cfg, err := parseConfig()
|
||||||
|
if err != nil {
|
||||||
|
panic(fmt.Errorf("error parsing command-line arguments: %s", err))
|
||||||
|
}
|
||||||
|
|
||||||
|
privateKey, addrPubKeyHash, err := decodeKeys(cfg)
|
||||||
|
if err != nil {
|
||||||
|
panic(fmt.Errorf("error decoding public key: %s", err))
|
||||||
|
}
|
||||||
|
|
||||||
|
client, err := connect(cfg)
|
||||||
|
if err != nil {
|
||||||
|
panic(fmt.Errorf("could not connect to RPC server: %s", err))
|
||||||
|
}
|
||||||
|
log.Infof("Connected to server %s", cfg.RPCServer)
|
||||||
|
|
||||||
|
fundingOutPoint, fundingTx, err := findUnspentTXO(cfg, client, addrPubKeyHash)
|
||||||
|
if err != nil {
|
||||||
|
panic(fmt.Errorf("error finding unspent transactions: %s", err))
|
||||||
|
}
|
||||||
|
if fundingOutPoint == nil || fundingTx == nil {
|
||||||
|
panic(fmt.Errorf("could not find any unspent transactions this for key"))
|
||||||
|
}
|
||||||
|
log.Infof("Found transaction to spend: %s:%d", fundingOutPoint.TxID, fundingOutPoint.Index)
|
||||||
|
|
||||||
|
registryTx, err := buildSubnetworkRegistryTx(cfg, fundingOutPoint, fundingTx, privateKey)
|
||||||
|
if err != nil {
|
||||||
|
panic(fmt.Errorf("error building subnetwork registry tx: %s", err))
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = client.SendRawTransaction(registryTx, true)
|
||||||
|
if err != nil {
|
||||||
|
panic(fmt.Errorf("failed sending subnetwork registry tx: %s", err))
|
||||||
|
}
|
||||||
|
log.Infof("Successfully sent subnetwork registry transaction")
|
||||||
|
|
||||||
|
subnetworkID, err := blockdag.TxToSubnetworkID(registryTx)
|
||||||
|
if err != nil {
|
||||||
|
panic(fmt.Errorf("could not build subnetwork ID: %s", err))
|
||||||
|
}
|
||||||
|
|
||||||
|
err = waitForSubnetworkToBecomeAccepted(client, subnetworkID)
|
||||||
|
if err != nil {
|
||||||
|
panic(fmt.Errorf("error waiting for subnetwork to become accepted: %s", err))
|
||||||
|
}
|
||||||
|
log.Infof("Subnetwork '%s' was successfully registered.", subnetworkID)
|
||||||
|
}
|
||||||
|
|
||||||
|
func waitForSubnetworkToBecomeAccepted(client *rpcclient.Client, subnetworkID *subnetworkid.SubnetworkID) error {
|
||||||
|
retries := 0
|
||||||
|
for {
|
||||||
|
_, err := client.GetSubnetwork(subnetworkID.String())
|
||||||
|
if err != nil {
|
||||||
|
if rpcError, ok := err.(*btcjson.RPCError); ok && rpcError.Code == btcjson.ErrRPCSubnetworkNotFound {
|
||||||
|
log.Infof("Subnetwork not found")
|
||||||
|
|
||||||
|
retries++
|
||||||
|
if retries == maxGetSubnetworkRetries {
|
||||||
|
return fmt.Errorf("failed to get subnetwork %d times: %s", maxGetSubnetworkRetries, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Infof("Waiting %d seconds...", int(getSubnetworkRetryDelay.Seconds()))
|
||||||
|
<-time.After(getSubnetworkRetryDelay)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
return fmt.Errorf("failed getting subnetwork: %s", err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
91
cmd/addsubnetwork/config.go
Normal file
91
cmd/addsubnetwork/config.go
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"github.com/daglabs/btcd/dagconfig"
|
||||||
|
"github.com/jessevdk/go-flags"
|
||||||
|
)
|
||||||
|
|
||||||
|
type config struct {
|
||||||
|
PrivateKey string `short:"k" long:"private-key" description:"Private key" required:"true"`
|
||||||
|
RPCUser string `short:"u" long:"rpcuser" description:"RPC username" required:"true"`
|
||||||
|
RPCPassword string `short:"P" long:"rpcpass" default-mask:"-" description:"RPC password" required:"true"`
|
||||||
|
RPCServer string `short:"s" long:"rpcserver" description:"RPC server to connect to" required:"true"`
|
||||||
|
RPCCert string `short:"c" long:"rpccert" description:"RPC server certificate chain for validation"`
|
||||||
|
DisableTLS bool `long:"notls" description:"Disable TLS"`
|
||||||
|
TestNet bool `long:"testnet" description:"Connect to testnet"`
|
||||||
|
SimNet bool `long:"simnet" description:"Connect to the simulation test network"`
|
||||||
|
DevNet bool `long:"devnet" description:"Connect to the development test network"`
|
||||||
|
GasLimit uint64 `long:"gaslimit" description:"The gas limit of the new subnetwork"`
|
||||||
|
RegistryTxFee uint64 `long:"regtxfee" description:"The fee for the subnetwork registry transaction"`
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
defaultSubnetworkGasLimit = 1000
|
||||||
|
defaultRegistryTxFee = 3000
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
activeNetParams dagconfig.Params
|
||||||
|
)
|
||||||
|
|
||||||
|
func parseConfig() (*config, error) {
|
||||||
|
cfg := &config{}
|
||||||
|
parser := flags.NewParser(cfg, flags.PrintErrors|flags.HelpFlag)
|
||||||
|
_, err := parser.Parse()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if cfg.RPCCert == "" && !cfg.DisableTLS {
|
||||||
|
return nil, errors.New("--notls has to be disabled if --cert is used")
|
||||||
|
}
|
||||||
|
|
||||||
|
if cfg.RPCCert != "" && cfg.DisableTLS {
|
||||||
|
return nil, errors.New("--cert should be omitted if --notls is used")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Multiple networks can't be selected simultaneously.
|
||||||
|
numNets := 0
|
||||||
|
if cfg.TestNet {
|
||||||
|
numNets++
|
||||||
|
}
|
||||||
|
if cfg.SimNet {
|
||||||
|
numNets++
|
||||||
|
}
|
||||||
|
if cfg.DevNet {
|
||||||
|
numNets++
|
||||||
|
}
|
||||||
|
if numNets > 1 {
|
||||||
|
return nil, errors.New("multiple net params (testnet, simnet, devnet, etc.) can't be used " +
|
||||||
|
"together -- choose one of them")
|
||||||
|
}
|
||||||
|
|
||||||
|
activeNetParams = dagconfig.MainNetParams
|
||||||
|
switch {
|
||||||
|
case cfg.TestNet:
|
||||||
|
activeNetParams = dagconfig.TestNet3Params
|
||||||
|
case cfg.SimNet:
|
||||||
|
activeNetParams = dagconfig.SimNetParams
|
||||||
|
case cfg.DevNet:
|
||||||
|
activeNetParams = dagconfig.DevNetParams
|
||||||
|
}
|
||||||
|
|
||||||
|
if cfg.GasLimit < 0 {
|
||||||
|
return nil, fmt.Errorf("gaslimit may not be smaller than 0")
|
||||||
|
}
|
||||||
|
if cfg.GasLimit == 0 {
|
||||||
|
cfg.GasLimit = defaultSubnetworkGasLimit
|
||||||
|
}
|
||||||
|
|
||||||
|
if cfg.RegistryTxFee < 0 {
|
||||||
|
return nil, fmt.Errorf("regtxfee may not be smaller than 0")
|
||||||
|
}
|
||||||
|
if cfg.RegistryTxFee == 0 {
|
||||||
|
cfg.RegistryTxFee = defaultRegistryTxFee
|
||||||
|
}
|
||||||
|
|
||||||
|
return cfg, nil
|
||||||
|
}
|
37
cmd/addsubnetwork/connect.go
Normal file
37
cmd/addsubnetwork/connect.go
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/daglabs/btcd/rpcclient"
|
||||||
|
"io/ioutil"
|
||||||
|
)
|
||||||
|
|
||||||
|
func connect(cfg *config) (*rpcclient.Client, error) {
|
||||||
|
var cert []byte
|
||||||
|
if !cfg.DisableTLS {
|
||||||
|
var err error
|
||||||
|
cert, err = ioutil.ReadFile(cfg.RPCCert)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("error reading certificates file: %s", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
connCfg := &rpcclient.ConnConfig{
|
||||||
|
Host: cfg.RPCServer,
|
||||||
|
Endpoint: "ws",
|
||||||
|
User: cfg.RPCUser,
|
||||||
|
Pass: cfg.RPCPassword,
|
||||||
|
DisableTLS: cfg.DisableTLS,
|
||||||
|
}
|
||||||
|
|
||||||
|
if !cfg.DisableTLS {
|
||||||
|
connCfg.Certificates = cert
|
||||||
|
}
|
||||||
|
|
||||||
|
client, err := rpcclient.New(connCfg, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("error connecting to address %s: %s", cfg.RPCServer, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return client, nil
|
||||||
|
}
|
19
cmd/addsubnetwork/keys.go
Normal file
19
cmd/addsubnetwork/keys.go
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/daglabs/btcd/btcec"
|
||||||
|
"github.com/daglabs/btcd/util"
|
||||||
|
"github.com/daglabs/btcd/util/base58"
|
||||||
|
)
|
||||||
|
|
||||||
|
func decodeKeys(cfg *config) (*btcec.PrivateKey, *util.AddressPubKeyHash, error) {
|
||||||
|
privateKeyBytes := base58.Decode(cfg.PrivateKey)
|
||||||
|
privateKey, _ := btcec.PrivKeyFromBytes(btcec.S256(), privateKeyBytes)
|
||||||
|
serializedPrivateKey := privateKey.PubKey().SerializeCompressed()
|
||||||
|
|
||||||
|
pubKeyAddr, err := util.NewAddressPubKey(serializedPrivateKey, activeNetParams.Prefix)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
return privateKey, pubKeyAddr.AddressPubKeyHash(), nil
|
||||||
|
}
|
17
cmd/addsubnetwork/log.go
Normal file
17
cmd/addsubnetwork/log.go
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/btcsuite/btclog"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
type logWriter struct{}
|
||||||
|
|
||||||
|
func (logWriter) Write(p []byte) (n int, err error) {
|
||||||
|
return os.Stdout.Write(p)
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
backendLog = btclog.NewBackend(logWriter{})
|
||||||
|
log = backendLog.Logger("ASUB")
|
||||||
|
)
|
34
cmd/addsubnetwork/registrytx.go
Normal file
34
cmd/addsubnetwork/registrytx.go
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/daglabs/btcd/blockdag"
|
||||||
|
"github.com/daglabs/btcd/btcec"
|
||||||
|
"github.com/daglabs/btcd/txscript"
|
||||||
|
"github.com/daglabs/btcd/wire"
|
||||||
|
)
|
||||||
|
|
||||||
|
func buildSubnetworkRegistryTx(cfg *config, fundingOutPoint *wire.OutPoint, fundingTx *wire.MsgTx, privateKey *btcec.PrivateKey) (*wire.MsgTx, error) {
|
||||||
|
txIn := &wire.TxIn{
|
||||||
|
PreviousOutPoint: *fundingOutPoint,
|
||||||
|
Sequence: wire.MaxTxInSequenceNum,
|
||||||
|
}
|
||||||
|
pkScript, err := txscript.PayToScriptHashScript(blockdag.OpTrueScript)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
txOut := &wire.TxOut{
|
||||||
|
PkScript: pkScript,
|
||||||
|
Value: fundingTx.TxOut[fundingOutPoint.Index].Value - cfg.RegistryTxFee,
|
||||||
|
}
|
||||||
|
registryTx := wire.NewRegistryMsgTx(1, []*wire.TxIn{txIn}, []*wire.TxOut{txOut}, cfg.GasLimit)
|
||||||
|
|
||||||
|
SignatureScript, err := txscript.SignatureScript(registryTx, 0, fundingTx.TxOut[fundingOutPoint.Index].PkScript,
|
||||||
|
txscript.SigHashAll, privateKey, true)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to build signature script: %s", err)
|
||||||
|
}
|
||||||
|
txIn.SignatureScript = SignatureScript
|
||||||
|
|
||||||
|
return registryTx, nil
|
||||||
|
}
|
112
cmd/addsubnetwork/utxo.go
Normal file
112
cmd/addsubnetwork/utxo.go
Normal file
@ -0,0 +1,112 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/hex"
|
||||||
|
"fmt"
|
||||||
|
"github.com/daglabs/btcd/btcjson"
|
||||||
|
"github.com/daglabs/btcd/rpcclient"
|
||||||
|
"github.com/daglabs/btcd/util"
|
||||||
|
"github.com/daglabs/btcd/wire"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
resultsCount = 1000
|
||||||
|
minConfirmations = 10
|
||||||
|
)
|
||||||
|
|
||||||
|
func findUnspentTXO(cfg *config, client *rpcclient.Client, addrPubKeyHash *util.AddressPubKeyHash) (*wire.OutPoint, *wire.MsgTx, error) {
|
||||||
|
txs, err := collectTransactions(client, addrPubKeyHash)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
utxos := buildUTXOs(txs)
|
||||||
|
for outPoint, tx := range utxos {
|
||||||
|
// Skip TXOs that can't pay for registration
|
||||||
|
if tx.TxOut[outPoint.Index].Value < cfg.RegistryTxFee {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
return &outPoint, tx, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func collectTransactions(client *rpcclient.Client, addrPubKeyHash *util.AddressPubKeyHash) ([]*wire.MsgTx, error) {
|
||||||
|
txs := make([]*wire.MsgTx, 0)
|
||||||
|
skip := 0
|
||||||
|
for {
|
||||||
|
results, err := client.SearchRawTransactionsVerbose(addrPubKeyHash, skip, resultsCount, true, false, nil)
|
||||||
|
if err != nil {
|
||||||
|
// Break when there are no further txs
|
||||||
|
if rpcError, ok := err.(*btcjson.RPCError); ok && rpcError.Code == btcjson.ErrRPCNoTxInfo {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, result := range results {
|
||||||
|
// Mempool transactions bring about unnecessary complexity, so
|
||||||
|
// simply don't bother processing them
|
||||||
|
if result.IsInMempool {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
tx, err := parseRawTransactionResult(result)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to process SearchRawTransactionResult: %s", err)
|
||||||
|
}
|
||||||
|
if tx == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if !isTxMatured(tx, *result.Confirmations) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
txs = append(txs, tx)
|
||||||
|
}
|
||||||
|
|
||||||
|
skip += resultsCount
|
||||||
|
}
|
||||||
|
return txs, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseRawTransactionResult(result *btcjson.SearchRawTransactionsResult) (*wire.MsgTx, error) {
|
||||||
|
txBytes, err := hex.DecodeString(result.Hex)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to decode transaction bytes: %s", err)
|
||||||
|
}
|
||||||
|
var tx wire.MsgTx
|
||||||
|
reader := bytes.NewReader(txBytes)
|
||||||
|
err = tx.Deserialize(reader)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to deserialize transaction: %s", err)
|
||||||
|
}
|
||||||
|
return &tx, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func isTxMatured(tx *wire.MsgTx, confirmations uint64) bool {
|
||||||
|
if !tx.IsBlockReward() {
|
||||||
|
return confirmations >= minConfirmations
|
||||||
|
}
|
||||||
|
return confirmations >= activeNetParams.BlockRewardMaturity
|
||||||
|
}
|
||||||
|
|
||||||
|
func buildUTXOs(txs []*wire.MsgTx) map[wire.OutPoint]*wire.MsgTx {
|
||||||
|
utxos := make(map[wire.OutPoint]*wire.MsgTx)
|
||||||
|
for _, tx := range txs {
|
||||||
|
for i := range tx.TxOut {
|
||||||
|
outPoint := wire.NewOutPoint(tx.TxID(), uint32(i))
|
||||||
|
utxos[*outPoint] = tx
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, tx := range txs {
|
||||||
|
for _, input := range tx.TxIn {
|
||||||
|
delete(utxos, input.PreviousOutPoint)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return utxos
|
||||||
|
}
|
@ -857,7 +857,7 @@ func (mp *TxPool) maybeAcceptTransaction(tx *util.Tx, isNew, rateLimit, rejectDu
|
|||||||
|
|
||||||
// Check that transaction does not overuse GAS
|
// Check that transaction does not overuse GAS
|
||||||
msgTx := tx.MsgTx()
|
msgTx := tx.MsgTx()
|
||||||
if !msgTx.SubnetworkID.IsEqual(subnetworkid.SubnetworkIDNative) {
|
if !msgTx.SubnetworkID.IsEqual(subnetworkid.SubnetworkIDNative) && !msgTx.SubnetworkID.IsEqual(subnetworkid.SubnetworkIDRegistry) {
|
||||||
gasLimit, err := mp.cfg.DAG.SubnetworkStore.GasLimit(&msgTx.SubnetworkID)
|
gasLimit, err := mp.cfg.DAG.SubnetworkStore.GasLimit(&msgTx.SubnetworkID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
|
Loading…
x
Reference in New Issue
Block a user