You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
***Concept**: An identity whose ownership is governed by a boolean expression over a set of component identities, enabling OR-style (any one signer suffices) and AND-style (all signers required) multi-party control without a fixed M-of-N scheme.
238
+
***Policy Expression Syntax**: A string using `$N` slot references and the operators `AND`, `OR`, and parentheses:
239
+
-`$0 OR $1` — either component identity 0 or 1 can satisfy ownership alone.
240
+
-`$0 AND $1` — both component identity 0 and 1 must sign.
241
+
-`($0 OR $1) AND $2` — one of the first two parties plus the third must sign.
242
+
***Identity (Payload)**: An ASN.1-encoded `PolicyIdentity` sequence:
243
+
-`policy` (UTF8String): the boolean expression, e.g. `"$0 OR $1"`.
244
+
-`identities` (SEQUENCE OF OCTET STRING): ordered list of raw component identity bytes; `$N` indexes into this list.
-`IdentityAuditInfos` (array of `IdentityAuditInfo`): per-component audit info blobs in the same order as `identities`.
247
+
***Encoding**:
248
+
-`TypedIdentity` payload: ASN.1 DER.
249
+
- Audit Info: JSON.
250
+
***Signature Representation**: An ASN.1 `PolicySignature` (`SEQUENCE OF OCTET STRING`) where each slot corresponds to one component identity. A slot may be nil/empty when that component does not need to sign (valid for OR branches).
- Supporting a new identity type by implementing a custom `KeyManager`
259
277
- Customizing signature generation or verification logic within a `KeyManager`
260
278
- Providing a custom `KeyManagerProvider` to plug new identity mechanisms into `LocalMembership`
279
+
280
+
### Step-by-Step Guide: Introducing a New Identity Type
281
+
282
+
The steps below describe how to add a new composite identity type end-to-end, based on the pattern used for **PolicyIdentity** (`token/services/identity/boolpolicy`).
283
+
284
+
#### Step 1 — Reserve a type tag
285
+
286
+
Add a new constant to `token/driver/wallet.go` alongside the existing tags:
287
+
288
+
```go
289
+
const (
290
+
// ...existing tags...
291
+
MyNewIdentityTypeIdentityType = 7
292
+
MyNewIdentityTypeString = "mynew"
293
+
)
294
+
```
295
+
296
+
The integer must be unique across all registered identity types.
297
+
298
+
#### Step 2 — Define the wire format
299
+
300
+
Create a package (e.g. `token/services/identity/mynew/`) and define the identity struct. Use ASN.1 DER for structured binary data (as PolicyIdentity does) or JSON for human-readable payloads (as HTLC does):
Expose `Wrap` / `Unwrap` helpers (see `boolpolicy.WrapPolicyIdentity` / `boolpolicy.Unwrap`) that embed the serialized struct inside a `TypedIdentity` envelope with the new type tag.
316
+
317
+
#### Step 3 — Implement signature verification
318
+
319
+
Add a `Verifier` that accepts the new signature format and a `Deserializer` that reconstructs a `Verifier` from raw identity bytes. Register the deserializer via `des.AddTypedVerifierDeserializer(mynew.MyNewIdentityType, ...)` in each driver's `NewTokenService` (see `token/core/fabtoken/v1/driver/driver.go` and the zkatdlog equivalent).
320
+
321
+
#### Step 4 — Define the signature format
322
+
323
+
Define a struct for the signature produced over the token request (analogous to `PolicySignature` in `boolpolicy/sig.go`). Include ASN.1 or JSON encoding helpers and a `JoinSignatures` function if multiple parties contribute partial signatures.
324
+
325
+
#### Step 5 — Implement the `Authorization` checker
326
+
327
+
Create an `EscrowAuth` struct (see `token/services/ttx/boolpolicy/auth.go`) that implements the `Authorization` interface:
Create an `OwnerWallet` wrapper (see `token/services/ttx/boolpolicy/wallet.go`) that filters the unspent token list to tokens whose owner is the new identity type, and exposes domain-specific helpers (e.g. `VerifyApprover`).
353
+
354
+
#### Step 7 — Wire the recipient-negotiation protocol
355
+
356
+
If the new identity requires interactive negotiation between parties to assemble the composite identity before a transfer, add a `RequestMyNewIdentity` function following the pattern of `ttx.RequestPolicyIdentity` (`token/services/ttx/recipients.go`). The function sends a typed request, each counterparty responds with its component data, and the initiator assembles the final composite identity.
357
+
358
+
#### Step 8 — Add integration views
359
+
360
+
Create initiator and responder views in the integration layer (e.g. `integration/token/fungible/views/mynew.go`) following the pattern in `boolpolicy.go`:
361
+
362
+
-**Lock view** — transfers tokens to a recipient with the new composite identity.
363
+
-**Spend view** — spends those tokens, optionally with restricted signer sets.
364
+
-**Balance view** — queries the policy-owned token balance (modelled on `PolicyOwnedBalanceView`).
365
+
-**Responder views** — ACK and endorse spend requests for AND-style policies.
366
+
367
+
Register all view factories and responders in the integration SDK (`integration/token/fungible/sdk/party/sdk.go`).
368
+
369
+
#### Step 9 — Add tests
370
+
371
+
-**Unit tests** for the verifier (`sig_test.go` pattern) and for `EscrowAuth.IsMine` (`auth_test.go` pattern).
372
+
-**Integration tests** in `integration/token/fungible/tests.go` + the relevant `dlog_test.go``Describe` block, following `TestPolicyOR` / `TestPolicyAND`.
373
+
374
+
#### Summary checklist
375
+
376
+
| # | What | Where |
377
+
|:--|:-----|:------|
378
+
| 1 | Reserve type tag |`token/driver/wallet.go`|
379
+
| 2 | Wire format + Wrap/Unwrap |`token/services/identity/mynew/`|
380
+
| 3 | Verifier + Deserializer | same package; register in both drivers |
381
+
| 4 | Signature format + JoinSignatures | same package |
382
+
| 5 | EscrowAuth + register in drivers |`token/services/ttx/mynew/auth.go`|
The TTX service supports **PolicyIdentity** owners: tokens whose spending requires satisfying a boolean expression over a set of component identities. This enables richer access-control than simple multisig (M-of-N) — for example, an OR clause where any single co-owner may spend unilaterally, or complex nested expressions.
165
+
166
+
#### Creating a PolicyIdentity
167
+
168
+
Call `RequestPolicyIdentity` (in `token/services/ttx/recipients.go`) to negotiate a composite identity from all co-owners before building the transfer:
169
+
170
+
```go
171
+
recipient, err:= bptx.RequestRecipientIdentity(ctx, "$0 OR $1",
Each co-owner's node responds with its component identity; the SDK assembles the `PolicyIdentity` envelope automatically.
178
+
179
+
#### Policy Expression Syntax
180
+
181
+
| Expression | Meaning |
182
+
|:-----------|:--------|
183
+
|`$0 OR $1`| Either component 0 **or** component 1 can spend alone. |
184
+
|`$0 AND $1`| Both component 0 **and** component 1 must sign. |
185
+
|`($0 OR $1) AND $2`| One of the first two parties plus party 2 must sign. |
186
+
187
+
`$N` is a zero-based index into the ordered component identity list supplied when creating the token.
188
+
189
+
#### Spending — OR Policy
190
+
191
+
For an OR policy the initiator alone can satisfy the policy. Pass `WithPolicySigners` to restrict signature collection to only the signing party's slot; the remaining slots are left nil (which is valid for OR branches):
For an AND policy all co-owners must endorse. Use `RequestSpendView` (in `token/services/ttx/boolpolicy/spend.go`) to notify co-owners before assembling the transaction, then collect endorsements from all components without restriction:
Co-owners run `EndorseSpendView` (via `EndorseSpend`) on their side, which ACKs the spend request and then endorses the assembled transaction.
210
+
211
+
#### Wallet and Authorization
212
+
213
+
The `boolpolicy.OwnerWallet` (in `token/services/ttx/boolpolicy/wallet.go`) wraps a standard owner wallet and filters the token list to policy-type tokens. `VerifyApprover` can be used to assert that a given identity is one of the named component identities before allowing a spend.
214
+
215
+
The `EscrowAuth` struct (in `token/services/ttx/boolpolicy/auth.go`) implements the `Authorization` interface: `IsMine` returns true if any component identity of the policy token belongs to one of the node's owner wallets.
216
+
162
217
## Token Operations
163
218
164
219
The TTX service supports three primary operations through the `TokenRequest` API:
0 commit comments