-
Notifications
You must be signed in to change notification settings - Fork 38
/
nns.go
168 lines (145 loc) · 5.32 KB
/
nns.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
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
package client
import (
"errors"
"fmt"
"strconv"
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
"github.com/nspcc-dev/neo-go/pkg/rpcclient"
"github.com/nspcc-dev/neo-go/pkg/rpcclient/invoker"
"github.com/nspcc-dev/neo-go/pkg/util"
"github.com/nspcc-dev/neofs-contract/rpc/nns"
)
const (
// NNSAuditContractName is a name of the audit contract in NNS.
NNSAuditContractName = nns.NameAudit
// NNSBalanceContractName is a name of the balance contract in NNS.
NNSBalanceContractName = nns.NameBalance
// NNSContainerContractName is a name of the container contract in NNS.
NNSContainerContractName = nns.NameContainer
// NNSNeoFSIDContractName is a name of the neofsid contract in NNS.
NNSNeoFSIDContractName = nns.NameNeoFSID
// NNSNetmapContractName is a name of the netmap contract in NNS.
NNSNetmapContractName = nns.NameNetmap
// NNSProxyContractName is a name of the proxy contract in NNS.
NNSProxyContractName = nns.NameProxy
// NNSReputationContractName is a name of the reputation contract in NNS.
NNSReputationContractName = nns.NameReputation
)
var (
// ErrNNSRecordNotFound means that there is no such record in NNS contract.
ErrNNSRecordNotFound = errors.New("record has not been found in NNS contract")
)
// NNSAlphabetContractName returns contract name of the alphabet contract in NNS
// based on alphabet index.
func NNSAlphabetContractName(index int) string {
return nns.NameAlphabetPrefix + strconv.Itoa(index)
}
// NNSContractAddress returns contract address script hash based on its name
// in NNS contract.
// If script hash has not been found, returns ErrNNSRecordNotFound.
func (c *Client) NNSContractAddress(name string) (sh util.Uint160, err error) {
c.switchLock.RLock()
defer c.switchLock.RUnlock()
if c.inactive {
return util.Uint160{}, ErrConnectionLost
}
nnsHash, err := c.NNSHash()
if err != nil {
return util.Uint160{}, err
}
var nnsReader = nns.NewReader(invoker.New(c.client, nil), nnsHash)
return nnsReader.ResolveFSContract(name)
}
// NNSHash returns NNS contract hash.
func (c *Client) NNSHash() (util.Uint160, error) {
c.switchLock.RLock()
defer c.switchLock.RUnlock()
if c.inactive {
return util.Uint160{}, ErrConnectionLost
}
nnsHash := c.cache.nns()
if nnsHash == nil {
h, err := nns.InferHash(c.client)
if err != nil {
return util.Uint160{}, fmt.Errorf("InferHash: %w", err)
}
c.cache.setNNSHash(h)
nnsHash = &h
}
return *nnsHash, nil
}
// InitSidechainScope allows to replace [WithAutoSidechainScope] option and
// postpone Sidechain scope initialization when NNS contract is not yet ready
// while Client is already needed.
func (c *Client) InitSidechainScope() error {
c.switchLock.RLock()
defer c.switchLock.RUnlock()
if c.inactive {
return ErrConnectionLost
}
return autoSidechainScope(c.client, &c.cfg)
}
func autoSidechainScope(ws *rpcclient.WSClient, conf *cfg) error {
nnsHash, err := nns.InferHash(ws)
if err != nil {
return fmt.Errorf("resolve NNS contract address: %w", err)
}
var nnsReader = nns.NewReader(invoker.New(ws, nil), nnsHash)
balanceHash, err := nnsReader.ResolveFSContract(nns.NameBalance)
if err != nil {
return fmt.Errorf("resolve Balance contract address by NNS domain name %q: %w", nns.NameBalance, err)
}
cntHash, err := nnsReader.ResolveFSContract(nns.NameContainer)
if err != nil {
return fmt.Errorf("resolve Container contract address by NNS domain name %q: %w", nns.NameContainer, err)
}
netmapHash, err := nnsReader.ResolveFSContract(nns.NameNetmap)
if err != nil {
return fmt.Errorf("resolve Netmap contract address by NNS domain name %q: %w", nns.NameNetmap, err)
}
neofsIDHash, err := nnsReader.ResolveFSContract(nns.NameNeoFSID)
if err != nil {
return fmt.Errorf("resolve NeoFS ID contract address by NNS domain name %q: %w", nns.NameNeoFSID, err)
}
conf.signer = GetUniversalSignerScope(nnsHash, balanceHash, cntHash, netmapHash, neofsIDHash)
return nil
}
// GetUniversalSignerScope returns a universal (applicable for any valid NeoFS
// contract call) scope that should be used by IR and SNs. It contains a set of
// Rules for contracts calling each other and a regular CalledByEntry permission.
func GetUniversalSignerScope(nnsHash, balanceHash, cntHash, netmapHash, neofsIDHash util.Uint160) *transaction.Signer {
return &transaction.Signer{
Scopes: transaction.CalledByEntry | transaction.Rules,
Rules: []transaction.WitnessRule{{
Action: transaction.WitnessAllow,
Condition: &transaction.ConditionAnd{
(*transaction.ConditionCalledByContract)(&cntHash),
(*transaction.ConditionScriptHash)(&balanceHash),
},
}, {
Action: transaction.WitnessAllow,
Condition: &transaction.ConditionAnd{
(*transaction.ConditionCalledByContract)(&cntHash),
(*transaction.ConditionScriptHash)(&nnsHash),
},
}, {
Action: transaction.WitnessAllow,
Condition: &transaction.ConditionAnd{
(*transaction.ConditionCalledByContract)(&cntHash),
(*transaction.ConditionScriptHash)(&neofsIDHash),
},
}, {
Action: transaction.WitnessAllow,
Condition: &transaction.ConditionAnd{
(*transaction.ConditionCalledByContract)(&netmapHash),
(*transaction.ConditionScriptHash)(&cntHash),
},
}, {
Action: transaction.WitnessAllow,
Condition: &transaction.ConditionAnd{
(*transaction.ConditionCalledByContract)(&netmapHash),
(*transaction.ConditionScriptHash)(&balanceHash),
},
}},
}
}