Skip to content

Commit a180ea7

Browse files
adecaroclaude
andcommitted
fix(ttx): remove context.Context field from Transaction struct
Transaction stored a context.Context captured once at construction, so methods reached for t.Context instead of taking a context from their caller. A transaction rebuilt via NewTransactionFromBytes in a different view kept the originating view's context, and htlc.Transaction.Lock already accepted ctx but silently used t.Context instead, dropping the caller's deadline/cancellation/tracing context. Bytes, Issue, Transfer, Redeem, Upgrade, Outputs, and Inputs now take ctx explicitly, threaded through every call site in token/ and integration/. Also enables the containedctx linter and suppresses the pattern's remaining, reviewed occurrences (long-lived service/worker lifecycles, a per-event struct, session-wrapper convenience defaults, and a test fake) with a justification comment each. Fixes #2178 Fixes #2179 Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Signed-off-by: Angelo De Caro <adc@zurich.ibm.com>
1 parent d836273 commit a180ea7

56 files changed

Lines changed: 219 additions & 114 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.golangci.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
version: "2"
22
linters:
33
enable:
4+
- containedctx
45
- asasalint # Check for pass []any as any in variadic func(...any).
56
- canonicalheader # Canonicalheader checks whether net/http.Header uses canonical header. [auto-fix]
67
- copyloopvar # A linter detects places where loop variables are copied. [fast, auto-fix]

docs/token_sdk_usage.md

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ if err != nil {
5656
// 3. Issue Tokens
5757
// Use the issuer wallet to issue 'quantity' of 'tokenType' to 'recipient'.
5858
wallet := ttx.GetIssuerWallet(context, issuerWalletID)
59-
err = tx.Issue(wallet, recipient, tokenType, quantity)
59+
err = tx.Issue(context.Context(), wallet, recipient, tokenType, quantity)
6060
if err != nil {
6161
return nil, err
6262
}
@@ -99,6 +99,7 @@ if err != nil {
9999
// Sender wallet is used to select input tokens.
100100
senderWallet := ttx.GetWallet(context, senderWalletID)
101101
err = tx.Transfer(
102+
context.Context(),
102103
senderWallet,
103104
tokenType,
104105
[]uint64{amount},
@@ -147,6 +148,7 @@ if err != nil {
147148
// If needed, also pin the issuer signing key expected by public parameters.
148149
senderWallet := ttx.GetWallet(context, senderWalletID)
149150
err = tx.Redeem(
151+
context.Context(),
150152
senderWallet,
151153
tokenType,
152154
amount,
@@ -195,7 +197,7 @@ if err != nil {
195197

196198
// 3. Add Alice's Transfer
197199
senderWallet := ttx.GetWallet(context, aliceWallet)
198-
err = tx.Transfer(senderWallet, aliceTokenType, []uint64{aliceAmount}, []view.Identity{other})
200+
err = tx.Transfer(context.Context(), senderWallet, aliceTokenType, []uint64{aliceAmount}, []view.Identity{other})
199201
if err != nil {
200202
return nil, err
201203
}
@@ -239,7 +241,7 @@ if err != nil {
239241

240242
// 3. Add Bob's Transfer
241243
bobWallet := ttx.MyWalletFromTx(context, tx)
242-
err = tx.Transfer(bobWallet, action.Type, []uint64{action.Amount}, []view.Identity{action.Recipient})
244+
err = tx.Transfer(context.Context(), bobWallet, action.Type, []uint64{action.Amount}, []view.Identity{action.Recipient})
243245
if err != nil {
244246
return nil, err
245247
}
@@ -343,8 +345,8 @@ if err != nil {
343345
Uses an **Initiator-Responder Inversion** pattern. The user requests a withdrawal, and the Issuer (responder) becomes the initiator of the Token Transaction to issue the tokens.
344346

345347
### Multisig ([`multisig.go`](../integration/token/fungible/views/multisig.go))
346-
* **Lock**: `multisig.Wrap(tx).Lock(...)`
347-
* **Spend**: `multisig.Wrap(tx).Spend(...)`. Requires `multisig.Wallet` to list co-owned tokens.
348+
* **Lock**: `multisig.Wrap(tx).Lock(ctx, ...)`
349+
* **Spend**: `multisig.Wrap(tx).Spend(ctx, ...)`. Requires `multisig.Wallet` to list co-owned tokens.
348350

349351
---
350352

docs/upgradability.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ tx, err := ttx.NewTransaction(context, nil, ttx.WithTMSID(upgradeRequest.TMSID))
7474

7575
// The Upgrade call consumes old tokens and issues new ones in one atomic step
7676
err = tx.Upgrade(
77+
context.Context(),
7778
issuerWallet,
7879
upgradeRequest.RecipientIdentity,
7980
upgradeRequest.Challenge,

integration/token/dvp/views/auditor.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ func (a *AuditView) Call(context view.Context) (any, error) {
2424
// Validate
2525
auditor, err := ttx.NewAuditor(context, w)
2626
assert.NoError(err, "failed to get auditor instance")
27-
assert.NoError(auditor.Validate(tx), "failed auditing verification")
27+
assert.NoError(auditor.Validate(context.Context(), tx), "failed auditing verification")
2828

2929
return context.RunView(ttx.NewAuditApproveView(w, tx))
3030
}

integration/token/dvp/views/buyer.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ func (b *BuyHouseView) Call(context view.Context) (any, error) {
3232

3333
// check transaction, it must contain the house transfer
3434
nfttx := nfttx.Wrap(tx)
35-
outputs, err := nfttx.Outputs()
35+
outputs, err := nfttx.Outputs(context.Context())
3636
assert.NoError(err, "failed getting outputs")
3737
assert.NoError(outputs.Validate(), "failed validating outputs")
3838
assert.True(outputs.Count() == 1, "the transaction must contain one output")
@@ -54,6 +54,7 @@ func (b *BuyHouseView) Call(context view.Context) (any, error) {
5454

5555
// Append the cash transfer to the transaction
5656
err = tx.Transfer(
57+
context.Context(),
5758
ttx.MyWalletFromTx(context, tx),
5859
action.Type,
5960
[]uint64{action.Amount},

integration/token/dvp/views/cash/accept.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ func (a *AcceptCashView) Call(context view.Context) (any, error) {
3030
// The recipient can perform any check on the transaction as required by the business process
3131
// In particular, here, the recipient checks that the transaction contains at least one output, and
3232
// that there is at least one output that names the recipient. (The recipient is receiving something.
33-
outputs, err := tx.Outputs()
33+
outputs, err := tx.Outputs(context.Context())
3434
assert.NoError(err, "failed getting outputs")
3535
assert.True(outputs.Count() > 0)
3636
assert.True(outputs.ByRecipient(id).Count() > 0)

integration/token/dvp/views/cash/issue.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ func (p *IssueCashView) Call(context view.Context) (any, error) {
5555
wallet := ttx.GetIssuerWallet(context, p.IssuerWallet)
5656
assert.NotNil(wallet, "issuer wallet [%s] not found", p.IssuerWallet)
5757
err = tx.Issue(
58+
context.Context(),
5859
wallet,
5960
recipient,
6061
p.TokenType,

integration/token/dvp/views/house/accept.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ func (a *AcceptHouseView) Call(context view.Context) (any, error) {
2929
// The recipient can perform any check on the transaction as required by the business process
3030
// In particular, here, the recipient checks that the transaction contains one output that names the recipient.
3131
// (The recipient is receiving something)
32-
outputs, err := tx.Outputs()
32+
outputs, err := tx.Outputs(context.Context())
3333
assert.NoError(err, "failed getting outputs")
3434
assert.NoError(outputs.Validate(), "failed validating outputs")
3535
assert.True(outputs.Count() == 1, "the transaction must contain one output")

integration/token/dvp/views/house/issue.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ func (p *IssueHouseView) Call(context view.Context) (any, error) {
6262
uniqueID, err := uniqueness.GetService(context).ComputeID(context.Context(), h.Address)
6363
assert.NoError(err, "failed computing unique ID")
6464

65-
err = tx.Issue(wallet, h, recipient, nfttx.WithUniqueID(uniqueID))
65+
err = tx.Issue(context.Context(), wallet, h, recipient, nfttx.WithUniqueID(uniqueID))
6666
assert.NoError(err, "failed adding new issued token")
6767

6868
// The issuer is ready to collect all the required signatures.

integration/token/dvp/views/seller.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ func (d *SellHouseView) prepareHouseTransfer(context view.Context, tx *ttx.Trans
9999
assert.NotNil(wallet, "failed getting default wallet")
100100

101101
// Transfer ownership of the house to the buyer
102-
assert.NoError(nfttx.Wrap(tx).Transfer(wallet, house, buyer), "failed transferring house")
102+
assert.NoError(nfttx.Wrap(tx).Transfer(context.Context(), wallet, house, buyer), "failed transferring house")
103103

104104
return tx, house, nil
105105
}

0 commit comments

Comments
 (0)