|
| 1 | +package balancemgr |
| 2 | + |
| 3 | +import ( |
| 4 | + "context" |
| 5 | + |
| 6 | + "github.com/ipfs/go-cid" |
| 7 | + "golang.org/x/xerrors" |
| 8 | + |
| 9 | + "github.com/filecoin-project/go-address" |
| 10 | + |
| 11 | + "github.com/filecoin-project/curio/harmony/harmonydb" |
| 12 | + "github.com/filecoin-project/curio/harmony/harmonytask" |
| 13 | + "github.com/filecoin-project/curio/lib/proofsvc/common" |
| 14 | + |
| 15 | + "github.com/filecoin-project/lotus/api" |
| 16 | + "github.com/filecoin-project/lotus/chain/types" |
| 17 | +) |
| 18 | + |
| 19 | +func (b *BalanceMgrTask) adderProofshare(ctx context.Context, taskFunc harmonytask.AddTaskFunc, addr *balanceManagerAddress) error { |
| 20 | + svc := common.NewService(b.chain) |
| 21 | + idAddr, err := b.chain.StateLookupID(ctx, addr.SubjectAddress, types.EmptyTSK) |
| 22 | + if err != nil { |
| 23 | + return xerrors.Errorf("getting address ID: %w", err) |
| 24 | + } |
| 25 | + |
| 26 | + addrID, err := address.IDFromAddress(idAddr) |
| 27 | + if err != nil { |
| 28 | + return xerrors.Errorf("getting address ID: %w", err) |
| 29 | + } |
| 30 | + |
| 31 | + clientState, err := svc.GetClientState(ctx, addrID) |
| 32 | + if err != nil { |
| 33 | + return xerrors.Errorf("PSClientWallets: failed to get client state: %w", err) |
| 34 | + } |
| 35 | + |
| 36 | + sourceBalance, err := b.chain.StateGetActor(ctx, addr.SubjectAddress, types.EmptyTSK) |
| 37 | + if err != nil { |
| 38 | + return xerrors.Errorf("getting source balance: %w", err) |
| 39 | + } |
| 40 | + |
| 41 | + addr.SubjectBalance = types.BigInt(clientState.Balance) |
| 42 | + addr.SecondBalance = types.BigInt(sourceBalance.Balance) |
| 43 | + |
| 44 | + var shouldCreateTask bool |
| 45 | + switch addr.ActionType { |
| 46 | + case "requester": |
| 47 | + shouldCreateTask = addr.SubjectBalance.LessThan(addr.LowWatermarkFilBalance) |
| 48 | + } |
| 49 | + |
| 50 | + if shouldCreateTask { |
| 51 | + taskFunc(func(taskID harmonytask.TaskID, tx *harmonydb.Tx) (shouldCommit bool, seriousError error) { |
| 52 | + // check that address.ID has active_task_id = null, set the task ID, set last_ to null |
| 53 | + n, err := tx.Exec(` |
| 54 | + UPDATE balance_manager_addresses |
| 55 | + SET active_task_id = $1, last_msg_cid = NULL, last_msg_sent_at = NULL, last_msg_landed_at = NULL |
| 56 | + WHERE id = $2 AND active_task_id IS NULL AND (last_msg_cid IS NULL OR last_msg_landed_at IS NOT NULL) |
| 57 | + `, taskID, addr.ID) |
| 58 | + if err != nil { |
| 59 | + return false, xerrors.Errorf("updating balance manager address: %w", err) |
| 60 | + } |
| 61 | + |
| 62 | + return n > 0, nil |
| 63 | + }) |
| 64 | + } |
| 65 | + return nil |
| 66 | +} |
| 67 | + |
| 68 | +func (b *BalanceMgrTask) doProofshare(ctx context.Context, taskID harmonytask.TaskID, addr *balanceManagerAddress) (bool, error) { |
| 69 | + log.Infow("balancemgr proofshare Do", |
| 70 | + "id", addr.ID, |
| 71 | + "subject", addr.SubjectAddress, |
| 72 | + "low", types.FIL(addr.LowWatermarkFilBalance), |
| 73 | + "high", types.FIL(addr.HighWatermarkFilBalance)) |
| 74 | + |
| 75 | + svc := common.NewServiceCustomSend(b.chain, func(ctx context.Context, msg *types.Message, mss *api.MessageSendSpec) (cid.Cid, error) { |
| 76 | + mss.MaximizeFeeCap = true |
| 77 | + return b.sender.Send(ctx, msg, mss, "balancemgr-proofshare") |
| 78 | + }) |
| 79 | + idAddr, err := b.chain.StateLookupID(ctx, addr.SubjectAddress, types.EmptyTSK) |
| 80 | + if err != nil { |
| 81 | + return false, xerrors.Errorf("getting address ID: %w", err) |
| 82 | + } |
| 83 | + |
| 84 | + addrID, err := address.IDFromAddress(idAddr) |
| 85 | + if err != nil { |
| 86 | + return false, xerrors.Errorf("getting address ID: %w", err) |
| 87 | + } |
| 88 | + |
| 89 | + clientState, err := svc.GetClientState(ctx, addrID) |
| 90 | + if err != nil { |
| 91 | + return false, xerrors.Errorf("PSClientWallets: failed to get client state: %w", err) |
| 92 | + } |
| 93 | + |
| 94 | + sourceBalance, err := b.chain.StateGetActor(ctx, addr.SubjectAddress, types.EmptyTSK) |
| 95 | + if err != nil { |
| 96 | + return false, xerrors.Errorf("getting source balance: %w", err) |
| 97 | + } |
| 98 | + |
| 99 | + addr.SubjectBalance = types.BigInt(clientState.Balance) |
| 100 | + addr.SecondBalance = types.BigInt(sourceBalance.Balance) |
| 101 | + |
| 102 | + // calculate amount to send (based on latest chain balance) |
| 103 | + var amount types.BigInt |
| 104 | + var to address.Address |
| 105 | + var shouldSend bool |
| 106 | + |
| 107 | + if addr.ActionType != "requester" { |
| 108 | + return false, xerrors.Errorf("action type is not requester: %s", addr.ActionType) |
| 109 | + } |
| 110 | + |
| 111 | + if addr.SubjectBalance.LessThan(addr.LowWatermarkFilBalance) { |
| 112 | + amount = types.BigSub(addr.HighWatermarkFilBalance, addr.SubjectBalance) |
| 113 | + to = addr.SubjectAddress |
| 114 | + shouldSend = true |
| 115 | + } |
| 116 | + |
| 117 | + if !shouldSend { |
| 118 | + log.Infow("balance within watermarks, no action needed", |
| 119 | + "subject", addr.SubjectAddress, |
| 120 | + "balance", types.FIL(addr.SubjectBalance), |
| 121 | + "low", types.FIL(addr.LowWatermarkFilBalance), |
| 122 | + "high", types.FIL(addr.HighWatermarkFilBalance)) |
| 123 | + |
| 124 | + _, err = b.db.Exec(ctx, ` |
| 125 | + UPDATE balance_manager_addresses |
| 126 | + SET active_task_id = NULL, last_action = NOW() |
| 127 | + WHERE id = $1 |
| 128 | + `, addr.ID) |
| 129 | + if err != nil { |
| 130 | + return false, xerrors.Errorf("clearing task id: %w", err) |
| 131 | + } |
| 132 | + return true, nil |
| 133 | + } |
| 134 | + |
| 135 | + msgCid, err := svc.ClientDeposit(ctx, addr.SubjectAddress, amount) |
| 136 | + if err != nil { |
| 137 | + return false, xerrors.Errorf("ClientDeposit: %w", err) |
| 138 | + } |
| 139 | + |
| 140 | + _, err = b.db.Exec(ctx, `INSERT INTO message_waits (signed_message_cid) VALUES ($1)`, msgCid) |
| 141 | + if err != nil { |
| 142 | + return false, xerrors.Errorf("inserting into message_waits: %w", err) |
| 143 | + } |
| 144 | + |
| 145 | + _, err = b.db.Exec(ctx, ` |
| 146 | + UPDATE balance_manager_addresses |
| 147 | + SET last_msg_cid = $2, |
| 148 | + last_msg_sent_at = NOW(), |
| 149 | + last_msg_landed_at = NULL, |
| 150 | + active_task_id = NULL |
| 151 | + WHERE id = $1 |
| 152 | + `, addr.ID, msgCid.String()) |
| 153 | + if err != nil { |
| 154 | + return false, xerrors.Errorf("updating message cid: %w", err) |
| 155 | + } |
| 156 | + |
| 157 | + _, err = b.db.Exec(ctx, ` |
| 158 | + INSERT INTO proofshare_client_messages (signed_cid, wallet, action) |
| 159 | + VALUES ($1, $2, $3) |
| 160 | + `, msgCid, addrID, "deposit-bmgr") |
| 161 | + if err != nil { |
| 162 | + return false, xerrors.Errorf("addMessageTracking: failed to insert proofshare_client_messages: %w", err) |
| 163 | + } |
| 164 | + |
| 165 | + log.Infow("sent balance management message", |
| 166 | + "from", addr.SecondAddress, |
| 167 | + "to", to, |
| 168 | + "subjectType", "proofshare", |
| 169 | + "amount", types.FIL(amount), |
| 170 | + "msgCid", msgCid, |
| 171 | + "actionType", addr.ActionType) |
| 172 | + |
| 173 | + return true, nil |
| 174 | +} |
0 commit comments