From 5ec5ad8e1ed8b8fb16f946b99c793ac91f0857ef Mon Sep 17 00:00:00 2001 From: tequ Date: Fri, 3 Oct 2025 01:51:18 +0900 Subject: [PATCH] Deep Freeze XLS-77d (#2873) (#29) Co-authored-by: Chenna Keshava B S <21219765+ckeshava@users.noreply.github.com> Co-authored-by: Denis Angell --- .ci-config/xahaud.cfg | 6 +- packages/xahau/HISTORY.md | 1 + .../xahau/src/models/ledger/RippleState.ts | 4 ++ .../xahau/src/models/transactions/trustSet.ts | 10 +++ .../transactions/offerCreate.test.ts | 68 +++++++++++++++++-- .../integration/transactions/trustSet.test.ts | 58 ++++++++++++++++ packages/xahau/test/models/trustSet.test.ts | 5 ++ 7 files changed, 143 insertions(+), 9 deletions(-) diff --git a/.ci-config/xahaud.cfg b/.ci-config/xahaud.cfg index bc62973a..5d6ddcef 100644 --- a/.ci-config/xahaud.cfg +++ b/.ci-config/xahaud.cfg @@ -63,11 +63,6 @@ online_delete=256 [debug_logfile] /var/log/rippled/debug.log -[sntp_servers] -time.windows.com -time.apple.com -time.nist.gov -pool.ntp.org [ips] r.ripple.com 51235 @@ -167,6 +162,7 @@ fixXahauV1 fixXahauV2 fixXahauV3 PaychanAndEscrowForTokens +DeepFreeze Clawback [network_id] diff --git a/packages/xahau/HISTORY.md b/packages/xahau/HISTORY.md index da384a90..03a44637 100644 --- a/packages/xahau/HISTORY.md +++ b/packages/xahau/HISTORY.md @@ -6,6 +6,7 @@ Subscribe to [the **xrpl-announce** mailing list](https://groups.google.com/g/xr ### Added * parseTransactionFlags as a utility function in the xrpl package to streamline transactions flags-to-map conversion +* Support for XLS-77d Deep-Freeze amendment ### Fixed * `TransactionStream` model supports APIv2 diff --git a/packages/xahau/src/models/ledger/RippleState.ts b/packages/xahau/src/models/ledger/RippleState.ts index 907907e0..0250e63c 100644 --- a/packages/xahau/src/models/ledger/RippleState.ts +++ b/packages/xahau/src/models/ledger/RippleState.ts @@ -77,4 +77,8 @@ export enum RippleStateFlags { lsfHighFreeze = 0x00800000, // True, trust line to AMM. Used by client apps to identify payments via AMM. lsfAMMNode = 0x01000000, + // True, low side has set deep freeze flag + lsfLowDeepFreeze = 0x02000000, + // True, high side has set deep freeze flag + lsfHighDeepFreeze = 0x04000000, } diff --git a/packages/xahau/src/models/transactions/trustSet.ts b/packages/xahau/src/models/transactions/trustSet.ts index f584261a..229143fb 100644 --- a/packages/xahau/src/models/transactions/trustSet.ts +++ b/packages/xahau/src/models/transactions/trustSet.ts @@ -30,6 +30,11 @@ export enum TrustSetFlags { tfSetFreeze = 0x00100000, /** Unfreeze the trust line. */ tfClearFreeze = 0x00200000, + /** Deep-Freeze the trustline -- disallow sending and receiving the said IssuedCurrency */ + /** Allowed only if the trustline is already regularly frozen, or if tfSetFreeze is set in the same transaction. */ + tfSetDeepFreeze = 0x00400000, + /** Clear a Deep-Frozen trustline */ + tfClearDeepFreeze = 0x00800000, } /** @@ -89,6 +94,11 @@ export interface TrustSetFlagsInterface extends GlobalFlags { tfSetFreeze?: boolean /** Unfreeze the trust line. */ tfClearFreeze?: boolean + /** Deep-Freeze the trustline -- disallow sending and receiving the said IssuedCurrency */ + /** Allowed only if the trustline is already regularly frozen, or if tfSetFreeze is set in the same transaction. */ + tfSetDeepFreeze?: boolean + /** Clear a Deep-Frozen trust line */ + tfClearDeepFreeze?: boolean } /** diff --git a/packages/xahau/test/integration/transactions/offerCreate.test.ts b/packages/xahau/test/integration/transactions/offerCreate.test.ts index 7d7bf0f2..fb242544 100644 --- a/packages/xahau/test/integration/transactions/offerCreate.test.ts +++ b/packages/xahau/test/integration/transactions/offerCreate.test.ts @@ -1,24 +1,36 @@ import { assert } from 'chai' -import { OfferCreate } from '../../../src' +import { OfferCreate, TrustSet, Wallet } from '../../../src' import serverUrl from '../serverUrl' import { setupClient, teardownClient, type XrplIntegrationTestContext, } from '../setup' -import { testTransaction } from '../utils' +import { + testTransaction, + generateFundedWallet, + submitTransaction, +} from '../utils' // how long before each test case times out const TIMEOUT = 20000 describe('OfferCreate', function () { let testContext: XrplIntegrationTestContext + let wallet_deep_freeze_trustline: Wallet | undefined - beforeEach(async () => { + beforeAll(async () => { testContext = await setupClient(serverUrl) + if (!wallet_deep_freeze_trustline) { + // eslint-disable-next-line require-atomic-updates -- race condition doesn't really matter + wallet_deep_freeze_trustline = await generateFundedWallet( + testContext.client, + ) + } }) - afterEach(async () => teardownClient(testContext)) + + afterAll(async () => teardownClient(testContext)) it( 'base', @@ -49,4 +61,52 @@ describe('OfferCreate', function () { }, TIMEOUT, ) + + it( + 'OfferCreate with Deep-Frozen trustline must fail', + async () => { + assert(wallet_deep_freeze_trustline != null) + + // deep-freeze the trust line + const trust_set_tx: TrustSet = { + TransactionType: 'TrustSet', + Account: testContext.wallet.classicAddress, + LimitAmount: { + currency: 'USD', + issuer: wallet_deep_freeze_trustline.classicAddress, + value: '10', + }, + Flags: { + tfSetFreeze: true, + tfSetDeepFreeze: true, + }, + } + + await testTransaction( + testContext.client, + trust_set_tx, + testContext.wallet, + ) + + const offer_create_tx: OfferCreate = { + TransactionType: 'OfferCreate', + Account: testContext.wallet.classicAddress, + TakerGets: '13100000', + TakerPays: { + currency: 'USD', + issuer: wallet_deep_freeze_trustline.classicAddress, + value: '10', + }, + } + + const response = await submitTransaction({ + client: testContext.client, + transaction: offer_create_tx, + wallet: testContext.wallet, + }) + + assert.equal(response.result.engine_result, 'tecFROZEN') + }, + TIMEOUT, + ) }) diff --git a/packages/xahau/test/integration/transactions/trustSet.test.ts b/packages/xahau/test/integration/transactions/trustSet.test.ts index 7736d0d1..cabb6f7c 100644 --- a/packages/xahau/test/integration/transactions/trustSet.test.ts +++ b/packages/xahau/test/integration/transactions/trustSet.test.ts @@ -1,6 +1,8 @@ import { assert } from 'chai' import { TrustSet, percentToQuality, Wallet } from '../../../src' +import { RippleState } from '../../../src/models/ledger/index' +import { RippleStateFlags } from '../../../src/models/ledger/RippleState' import serverUrl from '../serverUrl' import { setupClient, @@ -85,4 +87,60 @@ describe('TrustSet', function () { }, TIMEOUT, ) + + it( + 'Create a Deep-Frozen trustline', + async () => { + assert(wallet2 != null) + // deep-freeze a trustline with the specified counter-party/currency-code + const tx: TrustSet = { + TransactionType: 'TrustSet', + Account: testContext.wallet.classicAddress, + LimitAmount: { + currency: 'USD', + issuer: wallet2.classicAddress, + value: '10', + }, + Flags: { + tfSetFreeze: true, + tfSetDeepFreeze: true, + }, + } + + const response = await testTransaction( + testContext.client, + tx, + testContext.wallet, + ) + assert.equal(response.result.engine_result, 'tesSUCCESS') + + // assert that the trustline is frozen + const trustLine = await testContext.client.request({ + command: 'account_lines', + account: testContext.wallet.classicAddress, + }) + assert.equal(trustLine.result.lines[0].freeze, true) + + // verify that the trust-line is deep-frozen + // this operation cannot be done with the account_lines RPC + const account_objects = await testContext.client.request({ + command: 'account_objects', + account: testContext.wallet.classicAddress, + }) + + const rippleState = account_objects.result + .account_objects[0] as RippleState + + // Depending on the pseudo-random generation of accounts, + // either of the below leger-object flags must be set + + const hasDeepFreeze = + // eslint-disable-next-line no-bitwise -- required to validate flag + (rippleState.Flags & RippleStateFlags.lsfHighDeepFreeze) | + // eslint-disable-next-line no-bitwise -- required to validate flag + (rippleState.Flags & RippleStateFlags.lsfLowDeepFreeze) + assert.isTrue(hasDeepFreeze !== 0) + }, + TIMEOUT, + ) }) diff --git a/packages/xahau/test/models/trustSet.test.ts b/packages/xahau/test/models/trustSet.test.ts index ce1b05eb..fe6cba95 100644 --- a/packages/xahau/test/models/trustSet.test.ts +++ b/packages/xahau/test/models/trustSet.test.ts @@ -22,6 +22,11 @@ describe('TrustSet', function () { }, QualityIn: 1234, QualityOut: 4321, + // an example of deep-frozen trustline + Flags: { + tfSetFreeze: true, + tfSetDeepFreeze: true, + }, } as any })