github.com/MetalBlockchain/metalgo@v1.11.9/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/MetalBlockchain/metalgo/database" 11 "github.com/MetalBlockchain/metalgo/ids" 12 "github.com/MetalBlockchain/metalgo/vms/components/verify" 13 "github.com/MetalBlockchain/metalgo/vms/platformvm/state" 14 "github.com/MetalBlockchain/metalgo/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 return creds, nil 47 } 48 49 // verifySubnetAuthorization carries out the validation for modifying a subnet. 50 // The last credential in [sTx.Creds] is used as the subnet authorization. 51 // Returns the remaining tx credentials that should be used to authorize the 52 // other operations in the tx. 53 func verifySubnetAuthorization( 54 backend *Backend, 55 chainState state.Chain, 56 sTx *txs.Tx, 57 subnetID ids.ID, 58 subnetAuth verify.Verifiable, 59 ) ([]verify.Verifiable, error) { 60 if len(sTx.Creds) == 0 { 61 // Ensure there is at least one credential for the subnet authorization 62 return nil, errWrongNumberOfCredentials 63 } 64 65 baseTxCredsLen := len(sTx.Creds) - 1 66 subnetCred := sTx.Creds[baseTxCredsLen] 67 68 subnetOwner, err := chainState.GetSubnetOwner(subnetID) 69 if err != nil { 70 return nil, err 71 } 72 73 if err := backend.Fx.VerifyPermission(sTx.Unsigned, subnetAuth, subnetCred, subnetOwner); err != nil { 74 return nil, fmt.Errorf("%w: %w", errUnauthorizedSubnetModification, err) 75 } 76 77 return sTx.Creds[:baseTxCredsLen], nil 78 }