github.com/filecoin-project/specs-actors/v4@v4.0.2/actors/builtin/verifreg/verified_registry_actor.go (about) 1 package verifreg 2 3 import ( 4 addr "github.com/filecoin-project/go-address" 5 "github.com/filecoin-project/go-state-types/abi" 6 "github.com/filecoin-project/go-state-types/cbor" 7 "github.com/ipfs/go-cid" 8 9 "github.com/filecoin-project/go-state-types/big" 10 "github.com/filecoin-project/go-state-types/exitcode" 11 verifreg0 "github.com/filecoin-project/specs-actors/actors/builtin/verifreg" 12 13 "github.com/filecoin-project/specs-actors/v4/actors/builtin" 14 "github.com/filecoin-project/specs-actors/v4/actors/runtime" 15 "github.com/filecoin-project/specs-actors/v4/actors/util/adt" 16 ) 17 18 type Actor struct{} 19 20 func (a Actor) Exports() []interface{} { 21 return []interface{}{ 22 builtin.MethodConstructor: a.Constructor, 23 2: a.AddVerifier, 24 3: a.RemoveVerifier, 25 4: a.AddVerifiedClient, 26 5: a.UseBytes, 27 6: a.RestoreBytes, 28 } 29 } 30 31 func (a Actor) Code() cid.Cid { 32 return builtin.VerifiedRegistryActorCodeID 33 } 34 35 func (a Actor) IsSingleton() bool { 36 return true 37 } 38 39 func (a Actor) State() cbor.Er { 40 return new(State) 41 } 42 43 var _ runtime.VMActor = Actor{} 44 45 //////////////////////////////////////////////////////////////////////////////// 46 // Actor methods 47 //////////////////////////////////////////////////////////////////////////////// 48 49 func (a Actor) Constructor(rt runtime.Runtime, rootKey *addr.Address) *abi.EmptyValue { 50 rt.ValidateImmediateCallerIs(builtin.SystemActorAddr) 51 52 // root should be an ID address 53 idAddr, ok := rt.ResolveAddress(*rootKey) 54 builtin.RequireParam(rt, ok, "root should be an ID address") 55 56 st, err := ConstructState(adt.AsStore(rt), idAddr) 57 builtin.RequireNoErr(rt, err, exitcode.ErrIllegalState, "failed to construct state") 58 rt.StateCreate(st) 59 return nil 60 } 61 62 //type AddVerifierParams struct { 63 // Address addr.Address 64 // Allowance DataCap 65 //} 66 type AddVerifierParams = verifreg0.AddVerifierParams 67 68 func (a Actor) AddVerifier(rt runtime.Runtime, params *AddVerifierParams) *abi.EmptyValue { 69 if params.Allowance.LessThan(MinVerifiedDealSize) { 70 rt.Abortf(exitcode.ErrIllegalArgument, "Allowance %d below MinVerifiedDealSize for add verifier %v", params.Allowance, params.Address) 71 } 72 73 verifier, err := builtin.ResolveToIDAddr(rt, params.Address) 74 builtin.RequireNoErr(rt, err, exitcode.ErrIllegalState, "failed to resolve verifier address %v to ID address", params.Address) 75 76 var st State 77 rt.StateReadonly(&st) 78 rt.ValidateImmediateCallerIs(st.RootKey) 79 80 if verifier == st.RootKey { 81 rt.Abortf(exitcode.ErrIllegalArgument, "Rootkey cannot be added as verifier") 82 } 83 rt.StateTransaction(&st, func() { 84 verifiers, err := adt.AsMap(adt.AsStore(rt), st.Verifiers, builtin.DefaultHamtBitwidth) 85 builtin.RequireNoErr(rt, err, exitcode.ErrIllegalState, "failed to load verifiers") 86 87 verifiedClients, err := adt.AsMap(adt.AsStore(rt), st.VerifiedClients, builtin.DefaultHamtBitwidth) 88 builtin.RequireNoErr(rt, err, exitcode.ErrIllegalState, "failed to load verified clients") 89 90 // A verified client cannot become a verifier 91 found, err := verifiedClients.Get(abi.AddrKey(verifier), nil) 92 builtin.RequireNoErr(rt, err, exitcode.ErrIllegalState, "failed get verified client state for %v", verifier) 93 if found { 94 rt.Abortf(exitcode.ErrIllegalArgument, "verified client %v cannot become a verifier", verifier) 95 } 96 97 err = verifiers.Put(abi.AddrKey(verifier), ¶ms.Allowance) 98 builtin.RequireNoErr(rt, err, exitcode.ErrIllegalState, "failed to add verifier") 99 100 st.Verifiers, err = verifiers.Root() 101 builtin.RequireNoErr(rt, err, exitcode.ErrIllegalState, "failed to flush verifiers") 102 }) 103 104 return nil 105 } 106 107 func (a Actor) RemoveVerifier(rt runtime.Runtime, verifierAddr *addr.Address) *abi.EmptyValue { 108 verifier, err := builtin.ResolveToIDAddr(rt, *verifierAddr) 109 builtin.RequireNoErr(rt, err, exitcode.ErrIllegalState, "failed to resolve verifier address %v to ID address", *verifierAddr) 110 111 var st State 112 rt.StateReadonly(&st) 113 rt.ValidateImmediateCallerIs(st.RootKey) 114 115 rt.StateTransaction(&st, func() { 116 verifiers, err := adt.AsMap(adt.AsStore(rt), st.Verifiers, builtin.DefaultHamtBitwidth) 117 builtin.RequireNoErr(rt, err, exitcode.ErrIllegalState, "failed to load verifiers") 118 119 found, err := verifiers.TryDelete(abi.AddrKey(verifier)) 120 builtin.RequireNoErr(rt, err, exitcode.ErrIllegalState, "failed to remove verifier") 121 builtin.RequireParam(rt, found, "no such verifier %v", verifierAddr) 122 123 st.Verifiers, err = verifiers.Root() 124 builtin.RequireNoErr(rt, err, exitcode.ErrIllegalState, "failed to flush verifiers") 125 }) 126 127 return nil 128 } 129 130 //type AddVerifiedClientParams struct { 131 // Address addr.Address 132 // Allowance DataCap 133 //} 134 type AddVerifiedClientParams = verifreg0.AddVerifiedClientParams 135 136 func (a Actor) AddVerifiedClient(rt runtime.Runtime, params *AddVerifiedClientParams) *abi.EmptyValue { 137 // The caller will be verified by checking the verifiers table below. 138 rt.ValidateImmediateCallerAcceptAny() 139 140 if params.Allowance.LessThan(MinVerifiedDealSize) { 141 rt.Abortf(exitcode.ErrIllegalArgument, "allowance %d below MinVerifiedDealSize for add verified client %v", params.Allowance, params.Address) 142 } 143 144 client, err := builtin.ResolveToIDAddr(rt, params.Address) 145 builtin.RequireNoErr(rt, err, exitcode.ErrIllegalState, "failed to resolve verified client address %v", params.Address) 146 147 var st State 148 rt.StateReadonly(&st) 149 if st.RootKey == client { 150 rt.Abortf(exitcode.ErrIllegalArgument, "Rootkey cannot be added as a verified client") 151 } 152 153 rt.StateTransaction(&st, func() { 154 verifiers, err := adt.AsMap(adt.AsStore(rt), st.Verifiers, builtin.DefaultHamtBitwidth) 155 builtin.RequireNoErr(rt, err, exitcode.ErrIllegalState, "failed to load verifiers") 156 157 verifiedClients, err := adt.AsMap(adt.AsStore(rt), st.VerifiedClients, builtin.DefaultHamtBitwidth) 158 builtin.RequireNoErr(rt, err, exitcode.ErrIllegalState, "failed to load verified clients") 159 160 // Validate caller is one of the verifiers. 161 verifier := rt.Caller() 162 var verifierCap DataCap 163 found, err := verifiers.Get(abi.AddrKey(verifier), &verifierCap) 164 builtin.RequireNoErr(rt, err, exitcode.ErrIllegalState, "failed to get verifier %v", verifier) 165 if !found { 166 rt.Abortf(exitcode.ErrNotFound, "no such verifier %v", verifier) 167 } 168 169 // Validate client to be added isn't a verifier 170 found, err = verifiers.Get(abi.AddrKey(client), nil) 171 builtin.RequireNoErr(rt, err, exitcode.ErrIllegalState, "failed to get verifier") 172 if found { 173 rt.Abortf(exitcode.ErrIllegalArgument, "verifier %v cannot be added as a verified client", client) 174 } 175 176 // Compute new verifier cap and update. 177 if verifierCap.LessThan(params.Allowance) { 178 rt.Abortf(exitcode.ErrIllegalArgument, "add more DataCap (%d) for VerifiedClient than allocated %d", params.Allowance, verifierCap) 179 } 180 newVerifierCap := big.Sub(verifierCap, params.Allowance) 181 182 err = verifiers.Put(abi.AddrKey(verifier), &newVerifierCap) 183 builtin.RequireNoErr(rt, err, exitcode.ErrIllegalState, "failed to update new verifier cap (%d) for %v", newVerifierCap, verifier) 184 185 // This is a one-time, upfront allocation. 186 // This allowance cannot be changed by calls to AddVerifiedClient as long as the client has not been removed. 187 // If parties need more allowance, they need to create a new verified client or use up the the current allowance 188 // and then create a new verified client. 189 found, err = verifiedClients.Get(abi.AddrKey(client), nil) 190 builtin.RequireNoErr(rt, err, exitcode.ErrIllegalState, "failed to get verified client %v", client) 191 if found { 192 rt.Abortf(exitcode.ErrIllegalArgument, "verified client already exists: %v", client) 193 } 194 195 err = verifiedClients.Put(abi.AddrKey(client), ¶ms.Allowance) 196 builtin.RequireNoErr(rt, err, exitcode.ErrIllegalState, "failed to add verified client %v with cap %d", client, params.Allowance) 197 198 st.Verifiers, err = verifiers.Root() 199 builtin.RequireNoErr(rt, err, exitcode.ErrIllegalState, "failed to flush verifiers") 200 201 st.VerifiedClients, err = verifiedClients.Root() 202 builtin.RequireNoErr(rt, err, exitcode.ErrIllegalState, "failed to flush verified clients") 203 }) 204 205 return nil 206 } 207 208 //type UseBytesParams struct { 209 // Address addr.Address // Address of verified client. 210 // DealSize abi.StoragePower // Number of bytes to use. 211 //} 212 type UseBytesParams = verifreg0.UseBytesParams 213 214 // Called by StorageMarketActor during PublishStorageDeals. 215 // Do not allow partially verified deals (DealSize must be greater than equal to allowed cap). 216 // Delete VerifiedClient if remaining DataCap is smaller than minimum VerifiedDealSize. 217 func (a Actor) UseBytes(rt runtime.Runtime, params *UseBytesParams) *abi.EmptyValue { 218 rt.ValidateImmediateCallerIs(builtin.StorageMarketActorAddr) 219 220 client, err := builtin.ResolveToIDAddr(rt, params.Address) 221 builtin.RequireNoErr(rt, err, exitcode.ErrIllegalState, "failed to resolve verified client address %v", params.Address) 222 223 if params.DealSize.LessThan(MinVerifiedDealSize) { 224 rt.Abortf(exitcode.ErrIllegalArgument, "VerifiedDealSize: %d below minimum in UseBytes", params.DealSize) 225 } 226 227 var st State 228 rt.StateTransaction(&st, func() { 229 verifiedClients, err := adt.AsMap(adt.AsStore(rt), st.VerifiedClients, builtin.DefaultHamtBitwidth) 230 builtin.RequireNoErr(rt, err, exitcode.ErrIllegalState, "failed to load verified clients") 231 232 var vcCap DataCap 233 found, err := verifiedClients.Get(abi.AddrKey(client), &vcCap) 234 builtin.RequireNoErr(rt, err, exitcode.ErrIllegalState, "failed to get verified client %v", client) 235 if !found { 236 rt.Abortf(exitcode.ErrNotFound, "no such verified client %v", client) 237 } 238 builtin.RequireState(rt, vcCap.GreaterThanEqual(big.Zero()), "negative cap for client %v: %v", client, vcCap) 239 240 if params.DealSize.GreaterThan(vcCap) { 241 rt.Abortf(exitcode.ErrIllegalArgument, "DealSize %d exceeds allowable cap: %d for VerifiedClient %v", params.DealSize, vcCap, client) 242 } 243 244 newVcCap := big.Sub(vcCap, params.DealSize) 245 if newVcCap.LessThan(MinVerifiedDealSize) { 246 // Delete entry if remaining DataCap is less than MinVerifiedDealSize. 247 // Will be restored later if the deal did not get activated with a ProvenSector. 248 // 249 // NOTE: Technically, client could lose up to MinVerifiedDealSize worth of DataCap. 250 // See: https://github.com/filecoin-project/specs-actors/issues/727 251 err = verifiedClients.Delete(abi.AddrKey(client)) 252 builtin.RequireNoErr(rt, err, exitcode.ErrIllegalState, "failed to delete verified client %v", client) 253 } else { 254 err = verifiedClients.Put(abi.AddrKey(client), &newVcCap) 255 builtin.RequireNoErr(rt, err, exitcode.ErrIllegalState, "failed to update verified client %v with %v", client, newVcCap) 256 } 257 258 st.VerifiedClients, err = verifiedClients.Root() 259 builtin.RequireNoErr(rt, err, exitcode.ErrIllegalState, "failed to flush verified clients") 260 }) 261 262 return nil 263 } 264 265 //type RestoreBytesParams struct { 266 // Address addr.Address 267 // DealSize abi.StoragePower 268 //} 269 type RestoreBytesParams = verifreg0.RestoreBytesParams 270 271 // Called by HandleInitTimeoutDeals from StorageMarketActor when a VerifiedDeal fails to init. 272 // Restore allowable cap for the client, creating new entry if the client has been deleted. 273 func (a Actor) RestoreBytes(rt runtime.Runtime, params *RestoreBytesParams) *abi.EmptyValue { 274 rt.ValidateImmediateCallerIs(builtin.StorageMarketActorAddr) 275 276 if params.DealSize.LessThan(MinVerifiedDealSize) { 277 rt.Abortf(exitcode.ErrIllegalArgument, "Below minimum VerifiedDealSize requested in RestoreBytes: %d", params.DealSize) 278 } 279 280 client, err := builtin.ResolveToIDAddr(rt, params.Address) 281 builtin.RequireNoErr(rt, err, exitcode.ErrIllegalState, "failed to resolve verified client addr %v", params.Address) 282 283 var st State 284 rt.StateReadonly(&st) 285 if st.RootKey == client { 286 rt.Abortf(exitcode.ErrIllegalArgument, "Cannot restore allowance for Rootkey") 287 } 288 289 rt.StateTransaction(&st, func() { 290 verifiedClients, err := adt.AsMap(adt.AsStore(rt), st.VerifiedClients, builtin.DefaultHamtBitwidth) 291 builtin.RequireNoErr(rt, err, exitcode.ErrIllegalState, "failed to load verified clients") 292 293 verifiers, err := adt.AsMap(adt.AsStore(rt), st.Verifiers, builtin.DefaultHamtBitwidth) 294 builtin.RequireNoErr(rt, err, exitcode.ErrIllegalState, "failed to load verifiers") 295 296 // validate we are NOT attempting to do this for a verifier 297 found, err := verifiers.Get(abi.AddrKey(client), nil) 298 builtin.RequireNoErr(rt, err, exitcode.ErrIllegalState, "failed tp get verifier") 299 if found { 300 rt.Abortf(exitcode.ErrIllegalArgument, "cannot restore allowance for a verifier") 301 } 302 303 var vcCap DataCap 304 found, err = verifiedClients.Get(abi.AddrKey(client), &vcCap) 305 builtin.RequireNoErr(rt, err, exitcode.ErrIllegalState, "failed to get verified client %v", client) 306 if !found { 307 vcCap = big.Zero() 308 } 309 310 newVcCap := big.Add(vcCap, params.DealSize) 311 err = verifiedClients.Put(abi.AddrKey(client), &newVcCap) 312 builtin.RequireNoErr(rt, err, exitcode.ErrIllegalState, "failed to put verified client %v with %v", client, newVcCap) 313 314 st.VerifiedClients, err = verifiedClients.Root() 315 builtin.RequireNoErr(rt, err, exitcode.ErrIllegalState, "failed to load verifiers") 316 }) 317 318 return nil 319 }