github.com/ava-labs/avalanchego@v1.11.11/vms/platformvm/txs/executor/subnet_tx_verification.go (about)

     1  // Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved.
     2  // See the file LICENSE for licensing terms.
     3  
     4  package executor
     5  
     6  import (
     7  	"errors"
     8  	"fmt"
     9  
    10  	"github.com/ava-labs/avalanchego/database"
    11  	"github.com/ava-labs/avalanchego/ids"
    12  	"github.com/ava-labs/avalanchego/vms/components/verify"
    13  	"github.com/ava-labs/avalanchego/vms/platformvm/state"
    14  	"github.com/ava-labs/avalanchego/vms/platformvm/txs"
    15  )
    16  
    17  var (
    18  	errWrongNumberOfCredentials       = errors.New("should have the same number of credentials as inputs")
    19  	errIsImmutable                    = errors.New("is immutable")
    20  	errUnauthorizedSubnetModification = errors.New("unauthorized subnet modification")
    21  )
    22  
    23  // verifyPoASubnetAuthorization carries out the validation for modifying a PoA
    24  // subnet. This is an extension of [verifySubnetAuthorization] that additionally
    25  // verifies that the subnet being modified is currently a PoA subnet.
    26  func verifyPoASubnetAuthorization(
    27  	backend *Backend,
    28  	chainState state.Chain,
    29  	sTx *txs.Tx,
    30  	subnetID ids.ID,
    31  	subnetAuth verify.Verifiable,
    32  ) ([]verify.Verifiable, error) {
    33  	creds, err := verifySubnetAuthorization(backend, chainState, sTx, subnetID, subnetAuth)
    34  	if err != nil {
    35  		return nil, err
    36  	}
    37  
    38  	_, err = chainState.GetSubnetTransformation(subnetID)
    39  	if err == nil {
    40  		return nil, fmt.Errorf("%q %w", subnetID, errIsImmutable)
    41  	}
    42  	if err != database.ErrNotFound {
    43  		return nil, err
    44  	}
    45  
    46  	_, _, err = chainState.GetSubnetManager(subnetID)
    47  	if err == nil {
    48  		return nil, fmt.Errorf("%q %w", subnetID, errIsImmutable)
    49  	}
    50  	if err != database.ErrNotFound {
    51  		return nil, err
    52  	}
    53  
    54  	return creds, nil
    55  }
    56  
    57  // verifySubnetAuthorization carries out the validation for modifying a subnet.
    58  // The last credential in [sTx.Creds] is used as the subnet authorization.
    59  // Returns the remaining tx credentials that should be used to authorize the
    60  // other operations in the tx.
    61  func verifySubnetAuthorization(
    62  	backend *Backend,
    63  	chainState state.Chain,
    64  	sTx *txs.Tx,
    65  	subnetID ids.ID,
    66  	subnetAuth verify.Verifiable,
    67  ) ([]verify.Verifiable, error) {
    68  	if len(sTx.Creds) == 0 {
    69  		// Ensure there is at least one credential for the subnet authorization
    70  		return nil, errWrongNumberOfCredentials
    71  	}
    72  
    73  	baseTxCredsLen := len(sTx.Creds) - 1
    74  	subnetCred := sTx.Creds[baseTxCredsLen]
    75  
    76  	subnetOwner, err := chainState.GetSubnetOwner(subnetID)
    77  	if err != nil {
    78  		return nil, err
    79  	}
    80  
    81  	if err := backend.Fx.VerifyPermission(sTx.Unsigned, subnetAuth, subnetCred, subnetOwner); err != nil {
    82  		return nil, fmt.Errorf("%w: %w", errUnauthorizedSubnetModification, err)
    83  	}
    84  
    85  	return sTx.Creds[:baseTxCredsLen], nil
    86  }