Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,10 @@ jobs:
run: pnpm test:stellar-bindings
working-directory: .

- name: Test names TTL keeper
run: pnpm test:stellar-keeper
working-directory: .

# The metrics indexer is a standalone Node package with its own lockfile
# (like evm/ and solana/). Install and test it so its RPC/health
# guarantees stay enforced; the root pnpm install does not cover it.
Expand Down
2 changes: 1 addition & 1 deletion AUTHORIZATION_MATRIX.md
Original file line number Diff line number Diff line change
Expand Up @@ -490,7 +490,7 @@ It covers:
| 16 | ThresholdNotMet | Guardian approvals < threshold |
| 17 | TooManyGuardians | >max guardians |
| 18 | InvalidThreshold | Guardian threshold invalid |
| 19 | InvalidExtendLedger | `extend_to ≤ current_ledger` |
| 19 | InvalidExtendLedger | `extend_to == 0` (TTL in ledgers from now) |
| 20 | ParentNotFound | Subdomain parent missing |
| 32 | Paused | Contract paused |
| 21 | MultisigNotInitialized | `init_multisig` not called |
Expand Down
7 changes: 7 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,23 @@
"scripts": {
"bindings:stellar": "tsx stellar/scripts/generate-bindings.ts",
"build:stellar": "pnpm bindings:stellar && cd stellar && cargo build --target wasm32-unknown-unknown --release",
fix/228-keeper-real-work-or-fail-closed
"test:stellar-bindings": "vitest run stellar/scripts/stealth-batch-sender-bindings.test.ts",
"test:stellar-keeper": "vitest run stellar/scripts/keeper/keeper.test.ts"
"test:stellar-bindings": "vitest run stellar/scripts/stealth-batch-sender-bindings.test.ts stellar/scripts/bindings-portability.test.ts"
develop
},
"pnpm": {
"onlyBuiltDependencies": ["esbuild"]
},
"devDependencies": {
"@stellar/stellar-sdk": "^15.1.0",
"@types/node": "^22.0.0",
fix/228-keeper-real-work-or-fail-closed
"commander": "^14.0.3",
"buffer": "6.0.3",
"esbuild": "^0.28.0",
develop
"tsx": "^4.19.2",
"typescript": "^5.7.0",
"vitest": "^2.1.9"
Expand Down
5 changes: 5 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion stellar/ERRORS.md
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ Code Name Meaning Introduced in
16 NamesError::ThresholdNotMet Recovery guardian threshold has not been met. pre-catalog
17 NamesError::TooManyGuardians Guardian set exceeds the supported size. pre-catalog
18 NamesError::InvalidThreshold Guardian or multisig threshold is invalid. pre-catalog
19 NamesError::InvalidExtendLedger Requested TTL extension ledger is not in the future. pre-catalog
19 NamesError::InvalidExtendLedger Requested TTL extension (`extend_to`, in ledgers from now) is zero. pre-catalog
20 NamesError::ParentNotFound Subdomain parent name does not exist. pre-catalog
21 NamesError::MultisigNotInitialized Protocol governance multisig has not been initialized. pre-catalog
22 NamesError::MultisigAlreadyInitialized Protocol governance multisig initialization was attempted more than once. pre-catalog
Expand Down
18 changes: 16 additions & 2 deletions stellar/PERF.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,20 @@ When adding features that deliberately increase instruction or resource usage pa
3. Re-run `cargo bench -p wraith-stellar-bench --bench gas -- --format json --out results.json`.
4. Commit the new `stellar/bench/baseline.json` and updated `stellar/PERF.md`.

### Names TTL extension is relative (issue #228)

`wraith-names::extend_name_ttl` and `bulk_renew` take `extend_to` as a TTL in
ledgers from now. Before, the contract passed the current ledger as the
`extend_ttl` threshold, so in the bench the contract instance top-up was skipped.
It is now performed, because the threshold is `extend_to`. `extend_name_ttl::existing` goes from 61,349 to
63,741 instructions (+3.9%) and from 5,506 to 6,354 memory bytes (+15.4%, about
850 bytes). Ledger entries, read/write bytes and event bytes are unchanged, and
no other benched op moves, including `bulk_renew` (which does not extend the
instance). Dropping the instance top-up brings the op down to 57,407
instructions and 5,118 bytes, but then the keeper would extend names while the
contract itself could expire, so the cost is the extension doing the work it
was meant to do.

### Received-amount check (issue #227)

`stealth-sender::send`, `stealth-sender::batch_send` and
Expand Down Expand Up @@ -101,7 +115,7 @@ ownership checks.
## Current Numbers

<!-- BENCH:CURRENT:START -->
These are the harness results auto-updated from `develop` (measured 2026-10-16, commit `71bdd4edb2ee`).
These are the harness results auto-updated from `develop` (measured 2026-10-21, commit `198cedc001f1`).

| Contract | Function | Parameters | Instructions | Mem bytes | Read entries | Write entries | Read bytes | Write bytes | Event bytes |
|---|---|---:|---:|---:|---:|---:|---:|---:|---:|
Expand Down Expand Up @@ -134,7 +148,7 @@ These are the harness results auto-updated from `develop` (measured 2026-10-16,
| wraith-names | bulk_renew | count=5 | 351158 | 25489 | 11 | 0 | 2584 | 0 | 1032 |
| wraith-names | bulk_renew | count=10 | 718431 | 51559 | 21 | 0 | 5064 | 0 | 1812 |
| wraith-names | bulk_renew | count=20 | 1511175 | 111799 | 41 | 0 | 10024 | 0 | 3372 |
| wraith-names | extend_name_ttl | existing | 61349 | 5506 | 4 | 0 | 656 | 0 | 264 |
| wraith-names | extend_name_ttl | existing | 63741 | 6354 | 4 | 0 | 656 | 0 | 264 |
| stealth-splitter | create_split | beneficiaries=5 | 121823 | 14396 | 1 | 2 | 180 | 1300 | 544 |
| stealth-splitter | create_split | beneficiaries=15 | 230548 | 38036 | 1 | 2 | 180 | 2700 | 544 |
| stealth-splitter | create_split | beneficiaries=25 | 343273 | 77676 | 1 | 2 | 180 | 4100 | 544 |
Expand Down
8 changes: 4 additions & 4 deletions stellar/abi/wraith_names.json
Original file line number Diff line number Diff line change
Expand Up @@ -394,7 +394,7 @@
},
{
"function_v0": {
"doc": "Renew (extend TTL for) multiple names in a single atomic transaction.\\n\\nAll names must exist. If any name is not found, the entire operation\\nreverts.",
"doc": "Renew (extend TTL for) multiple names in a single atomic transaction.\\n\\n`extend_to` is a TTL in ledgers counted from the current ledger, not a\\nledger sequence. Each name ends up live for at least `extend_to` more\\nledgers (capped by the network's max entry TTL).\\n\\nAll names must exist. If any name is not found, the entire operation\\nreverts.",
"name": "bulk_renew",
"inputs": [
{
Expand All @@ -408,7 +408,7 @@
},
{
"doc": "",
"name": "extend_to_ledger",
"name": "extend_to",
"type_": "u32"
}
],
Expand Down Expand Up @@ -1056,7 +1056,7 @@
},
{
"function_v0": {
"doc": "Extend TTL for persistent storage entries only.\\nExtend the TTL of a registered name to a future ledger.\\nThis is a permissionless function that anyone can call.\\nIdempotent: calling twice in the same ledger has no additional effect.",
"doc": "Extend the TTL of a registered name (its entry, reverse entry and the\\ncontract instance) so it stays live for at least `extend_to` more ledgers.\\n\\n`extend_to` is a TTL in ledgers counted from the current ledger, not a\\nledger sequence, and is capped by the network's max entry TTL. Entries\\nthat already have at least that much TTL left are left untouched.\\nThis is a permissionless function that anyone can call.",
"name": "extend_name_ttl",
"inputs": [
{
Expand All @@ -1066,7 +1066,7 @@
},
{
"doc": "",
"name": "extend_to_ledger",
"name": "extend_to",
"type_": "u32"
}
],
Expand Down
8 changes: 4 additions & 4 deletions stellar/bench/baseline.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"generated_at": "1792167500",
"commit": "71bdd4edb2ee33e5b88e36b6832cc633bc5704e9",
"generated_at": "1792569345",
"commit": "198cedc001f12cf21a1830a00e6fdc32a31d9712",
"threshold_pct": 5,
"results": [
{
Expand Down Expand Up @@ -355,8 +355,8 @@
"contract": "wraith-names",
"function": "extend_name_ttl",
"params": "existing",
"instructions": 61349,
"mem_bytes": 5506,
"instructions": 63741,
"mem_bytes": 6354,
"read_entries": 4,
"write_entries": 0,
"read_bytes": 656,
Expand Down
4 changes: 2 additions & 2 deletions stellar/bench/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -258,7 +258,7 @@ pub fn collect_rows() -> std::vec::Vec<Row> {
for i in 0..count {
client.register(&owner, &names.get(i).unwrap(), &metas.get(i).unwrap());
}
client.bulk_renew(&names, &(env.ledger().sequence() + 10_000));
client.bulk_renew(&names, &10_000);
},
));
}
Expand All @@ -273,7 +273,7 @@ pub fn collect_rows() -> std::vec::Vec<Row> {
let client = WraithNamesContractClient::new(env, &contract_id);
let n = SorobanString::from_str(env, "alice");
client.register(&Address::generate(env), &n, &bytes(env, 64, 9));
client.extend_name_ttl(&n, &(env.ledger().sequence() + 10_000));
client.extend_name_ttl(&n, &10_000);
},
));

Expand Down
21 changes: 14 additions & 7 deletions stellar/bindings/typescript/wraith-names/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -393,10 +393,14 @@ export interface Client {
* Construct and simulate a bulk_renew transaction. Returns an `AssembledTransaction` object which will have a `result` field containing the result of the simulation. If this transaction changes contract state, you will need to call `signAndSend()` on the returned object.
* Renew (extend TTL for) multiple names in a single atomic transaction.
*
* `extend_to` is a TTL in ledgers counted from the current ledger, not a
* ledger sequence. Each name ends up live for at least `extend_to` more
* ledgers (capped by the network's max entry TTL).
*
* All names must exist. If any name is not found, the entire operation
* reverts.
*/
bulk_renew: ({names, extend_to_ledger}: {names: Array<string>, extend_to_ledger: u32}, options?: MethodOptions) => Promise<AssembledTransaction<Result<void>>>
bulk_renew: ({names, extend_to}: {names: Array<string>, extend_to: u32}, options?: MethodOptions) => Promise<AssembledTransaction<Result<void>>>

/**
* Construct and simulate a claim_name transaction. Returns an `AssembledTransaction` object which will have a `result` field containing the result of the simulation. If this transaction changes contract state, you will need to call `signAndSend()` on the returned object.
Expand Down Expand Up @@ -481,12 +485,15 @@ export interface Client {

/**
* Construct and simulate a extend_name_ttl transaction. Returns an `AssembledTransaction` object which will have a `result` field containing the result of the simulation. If this transaction changes contract state, you will need to call `signAndSend()` on the returned object.
* Extend TTL for persistent storage entries only.
* Extend the TTL of a registered name to a future ledger.
* Extend the TTL of a registered name (its entry, reverse entry and the
* contract instance) so it stays live for at least `extend_to` more ledgers.
*
* `extend_to` is a TTL in ledgers counted from the current ledger, not a
* ledger sequence, and is capped by the network's max entry TTL. Entries
* that already have at least that much TTL left are left untouched.
* This is a permissionless function that anyone can call.
* Idempotent: calling twice in the same ledger has no additional effect.
*/
extend_name_ttl: ({name, extend_to_ledger}: {name: string, extend_to_ledger: u32}, options?: MethodOptions) => Promise<AssembledTransaction<Result<void>>>
extend_name_ttl: ({name, extend_to}: {name: string, extend_to: u32}, options?: MethodOptions) => Promise<AssembledTransaction<Result<void>>>

/**
* Construct and simulate a pending_rotation transaction. Returns an `AssembledTransaction` object which will have a `result` field containing the result of the simulation. If this transaction changes contract state, you will need to call `signAndSend()` on the returned object.
Expand Down Expand Up @@ -623,7 +630,7 @@ export class Client extends ContractClient {
"AAAAAAAAACdSZXR1cm5zIHRydWUgaWYgdGhlIGNvbnRyYWN0IGlzIHBhdXNlZC4AAAAACWlzX3BhdXNlZAAAAAAAAAAAAAABAAAAAQ==",
"AAAAAAAAADNDdXJyZW50IHByb3RvY29sLWxldmVsIGdvdmVybmFuY2UgcXVvcnVtIHRocmVzaG9sZC4AAAAACXRocmVzaG9sZAAAAAAAAAAAAAABAAAABA==",
"AAAAAgAAAA1TdG9yYWdlIGtleXMuAAAAAAAAAAAAAAdEYXRhS2V5AAAAAAsAAAABAAAAKU1hcHMgbmFtZSBoYXNoIChCeXRlc048MzI+KSB0byBOYW1lRW50cnkuAAAAAAAABE5hbWUAAAABAAAD7gAAACAAAAABAAAAPlJldmVyc2UgbG9va3VwOiBtZXRhLWFkZHJlc3MgaGFzaCAoQnl0ZXNOPDMyPikgdG8gbmFtZSBzdHJpbmcuAAAAAAAHUmV2ZXJzZQAAAAABAAAD7gAAACAAAAABAAAALVJlcGxheSBwcm90ZWN0aW9uIGZvciBzaWduZWQgb24tYmVoYWxmIGNhbGxzLgAAAAAAAAZSZXBsYXkAAAAAAAEAAAPuAAAAIAAAAAEAAAAbR3VhcmRpYW4gY29uZmlnIGZvciBhIG5hbWUuAAAAAAlHdWFyZGlhbnMAAAAAAAABAAAD7gAAACAAAAABAAAAJVBlbmRpbmcgcmVjb3ZlcnkgcHJvcG9zYWwgZm9yIGEgbmFtZS4AAAAAAAAIUmVjb3ZlcnkAAAABAAAD7gAAACAAAAAAAAAAFFBhdXNlIGFkbWluIGFkZHJlc3MuAAAABUFkbWluAAAAAAAAAAAAAB9XaGV0aGVyIHRoZSBjb250cmFjdCBpcyBwYXVzZWQuAAAAAAZQYXVzZWQAAAAAAAAAAAAuUHJvdG9jb2wtbGV2ZWwgZ292ZXJuYW5jZSBtdWx0aXNpZyBzaWduZXIgc2V0LgAAAAAAD011bHRpc2lnU2lnbmVycwAAAAAAAAAANFByb3RvY29sLWxldmVsIGdvdmVybmFuY2UgbXVsdGlzaWcgcXVvcnVtIHRocmVzaG9sZC4AAAARTXVsdGlzaWdUaHJlc2hvbGQAAAAAAAAAAAAAOFBlbmRpbmcgcHJvdG9jb2wtbGV2ZWwgc2lnbmVyLXJvdGF0aW9uIHByb3Bvc2FsLCBpZiBhbnkuAAAAD1BlbmRpbmdSb3RhdGlvbgAAAAAAAAAAMFBlbmRpbmcgYXVjdGlvbi1hZG1pbiByb3RhdGlvbiBwcm9wb3NhbCwgaWYgYW55LgAAABtQZW5kaW5nQXVjdGlvbkFkbWluUm90YXRpb24A",
"AAAAAAAAAJRSZW5ldyAoZXh0ZW5kIFRUTCBmb3IpIG11bHRpcGxlIG5hbWVzIGluIGEgc2luZ2xlIGF0b21pYyB0cmFuc2FjdGlvbi4KCkFsbCBuYW1lcyBtdXN0IGV4aXN0LiBJZiBhbnkgbmFtZSBpcyBub3QgZm91bmQsIHRoZSBlbnRpcmUgb3BlcmF0aW9uCnJldmVydHMuAAAACmJ1bGtfcmVuZXcAAAAAAAIAAAAAAAAABW5hbWVzAAAAAAAD6gAAABAAAAAAAAAAEGV4dGVuZF90b19sZWRnZXIAAAAEAAAAAQAAA+kAAAPtAAAAAAAAB9AAAAAKTmFtZXNFcnJvcgAA",
"AAAAAAAAAVNSZW5ldyAoZXh0ZW5kIFRUTCBmb3IpIG11bHRpcGxlIG5hbWVzIGluIGEgc2luZ2xlIGF0b21pYyB0cmFuc2FjdGlvbi4KCmBleHRlbmRfdG9gIGlzIGEgVFRMIGluIGxlZGdlcnMgY291bnRlZCBmcm9tIHRoZSBjdXJyZW50IGxlZGdlciwgbm90IGEKbGVkZ2VyIHNlcXVlbmNlLiBFYWNoIG5hbWUgZW5kcyB1cCBsaXZlIGZvciBhdCBsZWFzdCBgZXh0ZW5kX3RvYCBtb3JlCmxlZGdlcnMgKGNhcHBlZCBieSB0aGUgbmV0d29yaydzIG1heCBlbnRyeSBUVEwpLgoKQWxsIG5hbWVzIG11c3QgZXhpc3QuIElmIGFueSBuYW1lIGlzIG5vdCBmb3VuZCwgdGhlIGVudGlyZSBvcGVyYXRpb24KcmV2ZXJ0cy4AAAAACmJ1bGtfcmVuZXcAAAAAAAIAAAAAAAAABW5hbWVzAAAAAAAD6gAAABAAAAAAAAAACWV4dGVuZF90bwAAAAAAAAQAAAABAAAD6QAAA+0AAAAAAAAH0AAAAApOYW1lc0Vycm9yAAA=",
"AAAAAAAAAFZDbGFpbSBhIHdvbiBhdWN0aW9uOiByZWdpc3RlcnMgdGhlIG5hbWUgdG8gdGhlIHdpbm5lciB3aXRoIHRoZWlyCnN0ZWFsdGggbWV0YS1hZGRyZXNzLgAAAAAACmNsYWltX25hbWUAAAAAAAMAAAAAAAAABndpbm5lcgAAAAAAEwAAAAAAAAAEbmFtZQAAABAAAAAAAAAAFHN0ZWFsdGhfbWV0YV9hZGRyZXNzAAAADgAAAAEAAAPpAAAD7QAAAAAAAAfQAAAADEF1Y3Rpb25FcnJvcg==",
"AAAAAAAAAIdDb21taXQgYSBzZWFsZWQgYmlkLiBgY29tbWl0bWVudGAgaGlkZXMgdGhlIGJpZCBhbW91bnQ7IGBkZXBvc2l0YCBpcwp0cmFuc2ZlcnJlZCB0byB0aGUgY29udHJhY3QgYW5kIG11c3QgY292ZXIgdGhlIGJpZCByZXZlYWxlZCBsYXRlci4AAAAACmNvbW1pdF9iaWQAAAAAAAQAAAAAAAAABmJpZGRlcgAAAAAAEwAAAAAAAAAEbmFtZQAAABAAAAAAAAAACmNvbW1pdG1lbnQAAAAAA+4AAAAgAAAAAAAAAAdkZXBvc2l0AAAAAAsAAAABAAAD6QAAA+0AAAAAAAAH0AAAAAxBdWN0aW9uRXJyb3I=",
"AAAAAAAAAERSZXZlYWwgYSBwcmV2aW91c2x5IGNvbW1pdHRlZCBiaWQgYnkgZGlzY2xvc2luZyB0aGUgYW1vdW50IGFuZCBzYWx0LgAAAApyZXZlYWxfYmlkAAAAAAAEAAAAAAAAAAZiaWRkZXIAAAAAABMAAAAAAAAABG5hbWUAAAAQAAAAAAAAAAZhbW91bnQAAAAAAAsAAAAAAAAABHNhbHQAAAPuAAAAIAAAAAEAAAPpAAAD7QAAAAAAAAfQAAAADEF1Y3Rpb25FcnJvcg==",
Expand All @@ -637,7 +644,7 @@ export class Client extends ContractClient {
"AAAAAAAAAIhTdGFydCBhIHNlYWxlZC1iaWQgYXVjdGlvbiBmb3IgYSBwcmVtaXVtIG5hbWUgKDw9IDQgY2hhcnMsIHRvcC1sZXZlbCkuClBlcm1pc3Npb25sZXNzOiBhbnlvbmUgbWF5IG9wZW4gdGhlIGF1Y3Rpb24gZm9yIGFuIGVsaWdpYmxlIG5hbWUuAAAADXN0YXJ0X2F1Y3Rpb24AAAAAAAABAAAAAAAAAARuYW1lAAAAEAAAAAEAAAPpAAAD7QAAAAAAAAfQAAAADEF1Y3Rpb25FcnJvcg==",
"AAAAAAAAAC9SZWFkIHRoZSBhdWN0aW9uIGNvbmZpZ3VyYXRpb24sIGlmIGluaXRpYWxpemVkLgAAAAAOYXVjdGlvbl9jb25maWcAAAAAAAAAAAABAAAD6AAAB9AAAAANQXVjdGlvbkNvbmZpZwAAAA==",
"AAAAAAAAAMxTZXR0bGUgYW4gYXVjdGlvbiBhZnRlciB0aGUgcmV2ZWFsIHBoYXNlOiBwYXlzIHRoZSB3aW5uaW5nIGJpZCB0byB0aGUKdHJlYXN1cnkgYW5kIHJlZnVuZHMgdGhlIHdpbm5lcidzIGV4Y2VzcyBkZXBvc2l0LiBQZXJtaXNzaW9ubGVzcyBzbwpmdW5kcyBjYW4gbmV2ZXIgYmUgdHJhcHBlZCwgb3BlcmF0ZWQgYnkgdGhlIGFkbWluIHBlciB0aGUgcnVuYm9vay4AAAAOc2V0dGxlX2F1Y3Rpb24AAAAAAAEAAAAAAAAABG5hbWUAAAAQAAAAAQAAA+kAAAPtAAAAAAAAB9AAAAAMQXVjdGlvbkVycm9y",
"AAAAAAAAAOZFeHRlbmQgVFRMIGZvciBwZXJzaXN0ZW50IHN0b3JhZ2UgZW50cmllcyBvbmx5LgpFeHRlbmQgdGhlIFRUTCBvZiBhIHJlZ2lzdGVyZWQgbmFtZSB0byBhIGZ1dHVyZSBsZWRnZXIuClRoaXMgaXMgYSBwZXJtaXNzaW9ubGVzcyBmdW5jdGlvbiB0aGF0IGFueW9uZSBjYW4gY2FsbC4KSWRlbXBvdGVudDogY2FsbGluZyB0d2ljZSBpbiB0aGUgc2FtZSBsZWRnZXIgaGFzIG5vIGFkZGl0aW9uYWwgZWZmZWN0LgAAAAAAD2V4dGVuZF9uYW1lX3R0bAAAAAACAAAAAAAAAARuYW1lAAAAEAAAAAAAAAAQZXh0ZW5kX3RvX2xlZGdlcgAAAAQAAAABAAAD6QAAA+0AAAAAAAAH0AAAAApOYW1lc0Vycm9yAAA=",
"AAAAAAAAAZlFeHRlbmQgdGhlIFRUTCBvZiBhIHJlZ2lzdGVyZWQgbmFtZSAoaXRzIGVudHJ5LCByZXZlcnNlIGVudHJ5IGFuZCB0aGUKY29udHJhY3QgaW5zdGFuY2UpIHNvIGl0IHN0YXlzIGxpdmUgZm9yIGF0IGxlYXN0IGBleHRlbmRfdG9gIG1vcmUgbGVkZ2Vycy4KCmBleHRlbmRfdG9gIGlzIGEgVFRMIGluIGxlZGdlcnMgY291bnRlZCBmcm9tIHRoZSBjdXJyZW50IGxlZGdlciwgbm90IGEKbGVkZ2VyIHNlcXVlbmNlLCBhbmQgaXMgY2FwcGVkIGJ5IHRoZSBuZXR3b3JrJ3MgbWF4IGVudHJ5IFRUTC4gRW50cmllcwp0aGF0IGFscmVhZHkgaGF2ZSBhdCBsZWFzdCB0aGF0IG11Y2ggVFRMIGxlZnQgYXJlIGxlZnQgdW50b3VjaGVkLgpUaGlzIGlzIGEgcGVybWlzc2lvbmxlc3MgZnVuY3Rpb24gdGhhdCBhbnlvbmUgY2FuIGNhbGwuAAAAAAAAD2V4dGVuZF9uYW1lX3R0bAAAAAACAAAAAAAAAARuYW1lAAAAEAAAAAAAAAAJZXh0ZW5kX3RvAAAAAAAABAAAAAEAAAPpAAAD7QAAAAAAAAfQAAAACk5hbWVzRXJyb3IAAA==",
"AAAAAAAAAC1UaGUgcGVuZGluZyBzaWduZXItcm90YXRpb24gcHJvcG9zYWwsIGlmIGFueS4AAAAAAAAQcGVuZGluZ19yb3RhdGlvbgAAAAAAAAABAAAD6AAAB9AAAAAQUm90YXRpb25Qcm9wb3NhbA==",
"AAAAAAAAAEFVcGRhdGUgYSBuYW1lIG9uIGJlaGFsZiBvZiBhbiBvd25lciB1c2luZyBhIHNpZ25lZCBhdXRob3JpemF0aW9uLgAAAAAAABB1cGRhdGVfb25fYmVoYWxmAAAABQAAAAAAAAAFb3duZXIAAAAAAAATAAAAAAAAAARuYW1lAAAAEAAAAAAAAAAQbmV3X21ldGFfYWRkcmVzcwAAAA4AAAAAAAAACXNpZ25hdHVyZQAAAAAAA+4AAABAAAAAAAAAAAZleHBpcnkAAAAAAAYAAAABAAAD6QAAA+0AAAAAAAAH0AAAAApOYW1lc0Vycm9yAAA=",
"AAAAAQAAACJHdWFyZGlhbiBjb25maWd1cmF0aW9uIGZvciBhIG5hbWUuAAAAAAAAAAAADkd1YXJkaWFuQ29uZmlnAAAAAAACAAAAAAAAAAlndWFyZGlhbnMAAAAAAAPqAAAAEwAAAAAAAAAJdGhyZXNob2xkAAAAAAAABA==",
Expand Down
Loading
Loading