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 }