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 }