github.com/filecoin-project/specs-actors/v4@v4.0.2/actors/builtin/shared.go (about)

     1  package builtin
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"io"
     7  
     8  	addr "github.com/filecoin-project/go-address"
     9  	"github.com/filecoin-project/go-state-types/abi"
    10  	"github.com/filecoin-project/go-state-types/big"
    11  	"github.com/filecoin-project/go-state-types/exitcode"
    12  	builtin0 "github.com/filecoin-project/specs-actors/actors/builtin"
    13  	builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin"
    14  
    15  	"github.com/filecoin-project/specs-actors/v4/actors/runtime"
    16  )
    17  
    18  ///// Code shared by multiple built-in actors. /////
    19  
    20  // Default log2 of branching factor for HAMTs.
    21  // This value has been empirically chosen, but the optimal value for maps with different mutation profiles may differ.
    22  const DefaultHamtBitwidth = 5
    23  
    24  type BigFrac struct {
    25  	Numerator   big.Int
    26  	Denominator big.Int
    27  }
    28  
    29  // Wraps already-serialized bytes as CBOR-marshalable.
    30  type CBORBytes []byte
    31  
    32  func (b CBORBytes) MarshalCBOR(w io.Writer) error {
    33  	_, err := w.Write(b)
    34  	return err
    35  }
    36  
    37  func (b *CBORBytes) UnmarshalCBOR(r io.Reader) error {
    38  	var c bytes.Buffer
    39  	_, err := c.ReadFrom(r)
    40  	*b = c.Bytes()
    41  	return err
    42  }
    43  
    44  // Aborts with an ErrIllegalState if predicate is not true.
    45  // This method is intended for use like an assertion.
    46  // Don't use this shorthand for states which are logically possible, as it will hide (non-)coverage of
    47  // the Abort call from code coverage metrics.
    48  func RequireState(rt runtime.Runtime, predicate bool, msg string, args ...interface{}) {
    49  	if !predicate {
    50  		rt.Abortf(exitcode.ErrIllegalState, msg, args...)
    51  	}
    52  }
    53  
    54  // Aborts with an ErrIllegalArgument if predicate is not true.
    55  func RequireParam(rt runtime.Runtime, predicate bool, msg string, args ...interface{}) {
    56  	if !predicate {
    57  		rt.Abortf(exitcode.ErrIllegalArgument, msg, args...)
    58  	}
    59  }
    60  
    61  // Propagates a failed send by aborting the current method with the same exit code.
    62  func RequireSuccess(rt runtime.Runtime, e exitcode.ExitCode, msg string, args ...interface{}) {
    63  	if !e.IsSuccess() {
    64  		rt.Abortf(e, msg, args...)
    65  	}
    66  }
    67  
    68  // Aborts with a formatted message if err is not nil.
    69  // The provided message will be suffixed by ": %s" and the provided args suffixed by the err.
    70  func RequireNoErr(rt runtime.Runtime, err error, defaultExitCode exitcode.ExitCode, msg string, args ...interface{}) {
    71  	if err != nil {
    72  		newMsg := msg + ": %s"
    73  		newArgs := append(args, err)
    74  		code := exitcode.Unwrap(err, defaultExitCode)
    75  		rt.Abortf(code, newMsg, newArgs...)
    76  	}
    77  }
    78  
    79  func RequestMinerControlAddrs(rt runtime.Runtime, minerAddr addr.Address) (ownerAddr addr.Address, workerAddr addr.Address, controlAddrs []addr.Address) {
    80  	var addrs MinerAddrs
    81  	code := rt.Send(minerAddr, MethodsMiner.ControlAddresses, nil, abi.NewTokenAmount(0), &addrs)
    82  	RequireSuccess(rt, code, "failed fetching control addresses")
    83  
    84  	return addrs.Owner, addrs.Worker, addrs.ControlAddrs
    85  }
    86  
    87  // This type duplicates the Miner.ControlAddresses return type, to work around a circular dependency between actors.
    88  type MinerAddrs struct {
    89  	Owner        addr.Address
    90  	Worker       addr.Address
    91  	ControlAddrs []addr.Address
    92  }
    93  
    94  // Note: we could move this alias back to the mutually-importing packages that use it, now that they
    95  // can instead both alias the v2 version.
    96  //type ConfirmSectorProofsParams struct {
    97  //	Sectors []abi.SectorNumber
    98  //}
    99  type ConfirmSectorProofsParams = builtin0.ConfirmSectorProofsParams
   100  
   101  // ResolveToIDAddr resolves the given address to it's ID address form.
   102  // If an ID address for the given address dosen't exist yet, it tries to create one by sending a zero balance to the given address.
   103  func ResolveToIDAddr(rt runtime.Runtime, address addr.Address) (addr.Address, error) {
   104  	// if we are able to resolve it to an ID address, return the resolved address
   105  	idAddr, found := rt.ResolveAddress(address)
   106  	if found {
   107  		return idAddr, nil
   108  	}
   109  
   110  	// send 0 balance to the account so an ID address for it is created and then try to resolve
   111  	code := rt.Send(address, MethodSend, nil, abi.NewTokenAmount(0), &Discard{})
   112  	if !code.IsSuccess() {
   113  		return address, code.Wrapf("failed to send zero balance to address %v", address)
   114  	}
   115  
   116  	// now try to resolve it to an ID address -> fail if not possible
   117  	idAddr, found = rt.ResolveAddress(address)
   118  	if !found {
   119  		return address, fmt.Errorf("failed to resolve address %v to ID address even after sending zero balance", address)
   120  	}
   121  
   122  	return idAddr, nil
   123  }
   124  
   125  // Note: we could move this alias back to the mutually-importing packages that use it, now that they
   126  // can instead both alias the v2 version.
   127  // type ApplyRewardParams struct {
   128  // 	Reward  abi.TokenAmount
   129  // 	Penalty abi.TokenAmount
   130  // }
   131  type ApplyRewardParams = builtin2.ApplyRewardParams
   132  
   133  // Discard is a helper
   134  type Discard struct{}
   135  
   136  func (d *Discard) MarshalCBOR(_ io.Writer) error {
   137  	// serialization is a noop
   138  	return nil
   139  }
   140  
   141  func (d *Discard) UnmarshalCBOR(_ io.Reader) error {
   142  	// deserialization is a noop
   143  	return nil
   144  }