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