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), &params.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), &params.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  }