凍結

凍結機能

XRP Ledger は、規制の要求への対応や疑わしい活動を調査する間に利用可能な、XRP以外の残高を凍結する機能を提供します。凍結には3つの設定があります:

XRP Ledger 上では誰も特権的な場所を持たないため、凍結機能では取引先が XRP や他の取引先が発行した資産で取引を行うことを防ぐことはできません。誰もXRPを凍結することはできません。

凍結される残高が正か負かにかかわらず、すべての凍結設定を行うことができます。通貨の発行者または通貨の所有者のいずれもトラストラインを凍結することができます。しかしながら、通貨の保有者が発行者を凍結することによる影響はごく僅かです。

個別フリーズ

個別フリーズ機能はトラストライン上の設定です。発行アドレスが個別フリーズを有効に設定したとき、次のルールが適用されます:

  • 凍結されたトラストライン上の2つの当事者間での支払いはまだ行うことができます。
  • 凍結されたトラストラインの取引先は、その発行者への直接の支払いを除いて、そのトラストライン上の残高を減らすことができなくなります。取引先は発行者に対しての直接的な凍結された残高の送金だけを行うことができます。
  • その取引先は凍結されたトラストライン上の他の取引先からの支払いは受け取ることができます。
  • その取引先の凍結されたトラストライン上で発行された通貨の売り注文は積み立て不足と見なされます。

金融機関は、取引先が疑わしい行為を示したり、金融機関の利用規約に違反したりするとその取引先と取引先を結びつけるトラストラインを凍結することができます。金融機関は、XRP Ledger に関連する金融機関が運営する他のシステムの取引先を凍結する必要もあります。(そうでなければ、金融機関を通じて支払いを送信することによって、依然として望ましくない活動に巻き込まれる可能性があります。)

個別アドレスは、金融機関へのトラストラインを凍結することができます。これは、その金融機関と他のユーザーとの間の取引には影響しません。ただし、オペレーショナル・アドレスを含む他のアドレスが、その金融機関の発行残高をその個別アドレスに送信するすることはできません。このタイプの個別フリーズは注文に影響しません。

個別フリーズは、単一通貨のみに適用されます。特定の取引先の複数の通貨を凍結するには、各通貨のトラストラインで個別フリーズを個別に有効にする必要があります。

ノー・フリーズ設定を有効にしている場合、アドレスは個別フリーズ設定を有効にすることはできません。

グローバル・フリーズ

グローバル・フリーズ機能はアドレス上の設定です。発行アドレスがグローバル・フリーズ機能を有効に設定したとき、次のルールが適用されます:

  • すべての凍結された発行アドレスの取引先は、発行者への直接的な支払いを除いて、凍結されたアドレスに対するトラストラインの残高を減らすことができなくなります。(これはオペレーショナル・アドレスにも影響します。)
  • 凍結された発行アドレスの取引先は、その発行アドレスからの直接的な支払いの受け取り、またはその発行アドレスへの直接的な支払いの送金はまだ行うことが出来ます。
  • 凍結されたアドレスによって発行された通貨のすべての売り注文は積み立て不足と見なされます。

オペレーショナル・アドレスのシークレット・キーが漏洩した場合に、そのようなアドレスのコントロールを取り戻した後でも、金融機関の発行アドレスでグローバル・フリーズを有効にすることは有用です。これは、資金の流れを止め、攻撃者がそれ以上のお金を持ち出すのを防ぐか、または少なくとも何が起こったかを追跡するのを容易にします。金融機関は、XRP Ledger でグローバル・フリーズを実施するほかに、外部システムへのコネクターでも活動を停止する必要があります。

また、金融機関が新しい発行アドレスに移行しようとしている場合や、金融機関が業務を中断しようとしている場合に、グローバル・フリーズを有効にするのも有用です。これにより特定の時点で資金がロックされるため、ユーザーは他の通貨で取引することはできません。

グローバル・フリーズは、そのアドレスによって発行、保有されているすべての通貨に適用されます。グローバル・フリーズを一つの通貨に対して有効にすることはできません。一部の通貨を凍結する機能を持たせたい場合は、通貨ごとに異なるアドレスを使用する必要があります。

アドレスは、いつでもグローバル・フリーズ設定を有効にすることができます。ただし、そのアドレスがノー・フリーズ設定を有効にした場合、グローバル・フリーズを無効にすることはできなくなります。

ノー・フリーズ

ノー・フリーズ機能は、取引先を凍結する能力を恒久的に放棄するアドレス上の設定です。企業は、この機能を使用して、発行さえれた資金を「物理的なお金のようなもの」として扱うことができます。ノー・フリーズ設定には2つの効果があります:

  • その発行アドレスは、すべての取引先に対するトラストライン上の個別フリーズを有効にできなくなります。
  • その発行アドレスは、グローバル・フリーズを有効にすることはまだ出来ますが、グローバル・フリーズを無効にすることはできません。

XRP Ledger は、発行された資産が表す債務を金融機関に賦課させるよう強制することはできません。したがって、グローバル・フリーズを有効にする能力を放棄しても、顧客を保護することはできません。ただし、グローバル・フリーズを無効にする能力を放棄することで、グローバル・フリーズ機能が一部の顧客に対して不公平に使用されないことを保証できます。

ノー・フリーズ設定は、アドレスとの間で発行するまたは発行されるすべての通貨に適用されます。他の通貨を除くいくつかの通貨を凍結したい場合、通貨ごとに異なるアドレスを使用する必要があります。

ノー・フリーズ設定は、アドレスのマスターキーの秘密鍵で署名されたトランザクションでのみ有効にすることができます。ノー・フリーズを有効にするために、レギュラーキーまたはマルチサイン・トランザクションを使用することはできません。

技術的な詳細

個別フリーズを有効・無効にする

rippled を使う

特定のトラストラインで個別フリーズを有効または無効にするには、TrustSet トランザクションを送信します。凍結を有効にするには tfSetFreeze フラグを使用し、凍結を無効にするには tfClearFreeze フラグを使用します。トランザクションのフィールドは次のようになります:

フィールド 説明
Account String The Ripple address to enable or disable the freeze.
TransactionType String TrustSet
LimitAmount Object Object defining the trust line to freeze.
LimitAmount.currency String Currency of the trust line
LimitAmount.issuer String The Ripple address of the counterparty to freeze
LimitAmount.value String The amount of currency you trust this counterparty to issue to you, as a quoted number. From the perspective of a financial institution, this is typically "0".
Flags Number To enable a freeze, use a value with the bit 0x00100000 (tfSetFreeze) enabled. To disable a freeze, use a value with the bit 0x00200000 (tfClearFreeze) enabled instead.

Fee、Sequence、および LastLedgerSequence パラメータを通常の方法で設定してください。

WebSocket API を使用して個別フリーズを有効にする TrustSet トランザクションを送信する例:

{
  "id": 12,
  "command": "submit",
  "tx_json": {
    "TransactionType": "TrustSet",
    "Account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
    "Fee": "12000",
    "Flags": 1048576,
    "LastLedgerSequence": 18103014,
    "LimitAmount": {
      "currency": "USD",
      "issuer": "rsA2LpzuawewSBQXkiju3YQTMzW13pAAdW",
      "value": "110"
    },
    "Sequence": 340
  },
  "secret": "s████████████████████████████",
  "offline": false,
  "fee_mult_max": 1000
}

注意: シークレットキーを信頼できないサーバーまたは安全でないチャネルに送信しないでください。

RippleAPI を使う

特定のトラストラインで個別フリーズを有効または無効にするには prepareTrustline メソッドを使用して Trustline トランザクションを準備します。trustline パラメータのフィールドは、次のように設定する必要があります:

フィールド 説明
currency String The currency of the trust line to freeze
counterparty String The Ripple address of the counterparty
limit String The amount of currency you trust this counterparty to issue to you, as a quoted number. From the perspective of a financial institution, this is typically "0".
frozen Boolean true to enable Individual Freeze on this trust line. false to disable Individual Freeze.

残りのトランザクションフローは、他のトランザクションと同じです。

トラストライン上で個別フリーズを有効にする JavaScript (ECMAScript 6)コードの例:

const {RippleAPI} = require('ripple-lib');

const api = new RippleAPI({
  server: 'wss://s1.ripple.com' // Public rippled server
});
api.on('error', (errorCode, errorMessage) => {
  console.log(errorCode + ': ' + errorMessage);
});

const issuing_address = 'rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn';
const issuing_secret = 's████████████████████████████';
    // Best practice: get your secret from an encrypted
    //  config file instead
const address_to_freeze = 'rUpy3eEg8rqjqfUoLeBnZkscbKbFsKXC3v';
const currency_to_freeze = 'USD';

api.connect().then(() => {

  // Look up current state of trust line
  const options = {counterparty: address_to_freeze,
                 currency: currency_to_freeze};
  console.log('looking up', currency_to_freeze, 'trust line from',
              issuing_address, 'to', address_to_freeze);
  return api.getTrustlines(issuing_address, options);

}).then(data => {

  // Prepare a trustline transaction to enable freeze
  let trustline = {};
  if (data.length !== 1) {
    console.log('trustline not found, making a default one');
    trustline = {
      currency: currency_to_freeze,
      counterparty: address_to_freeze,
      limit: 0
    };
  } else {
    trustline = data[0].specification;
    console.log('trustline found. previous state:', trustline);
  }

  trustline.frozen = true;

  console.log('preparing trustline transaction for line:', trustline);
  return api.prepareTrustline(issuing_address, trustline);

}).then(prepared_tx => {

  // Sign and submit the trustline transaction
  console.log('signing tx:', prepared_tx.txJSON);
  const signed1 = api.sign(prepared_tx.txJSON, issuing_secret);
  console.log('submitting tx:', signed1.id);

  return api.submit(signed1.signedTransaction);
}).then(() => {
  return api.disconnect();
}).catch(console.error);

グローバル・フリーズを有効・無効にする

rippled を使う

アドレス上のグローバル・フリーズを有効にするには、SetFlag フィールドに asfGlobalFreeze フラグ値を指定して AccountSet トランザクションを送信します。グローバル・フリーズを無効にするには、代わりに ClearFlag フィールドに asfGlobalFreeze フラグ値を設定します。

WebSocket API を使用してグローバル・フリーズを有効にする AccountSet トランザクションを送信する例:

{
  "id": 12,
  "command": "submit",
  "tx_json": {
    "TransactionType": "AccountSet",
    "Account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
    "Fee": "12000",
    "Flags": 0,
    "SetFlag": 7,
    "LastLedgerSequence": 18122753,
    "Sequence": 349
  },
  "secret": "s████████████████████████████",
  "offline": false,
  "fee_mult_max": 1000
}

注意: シークレットキーを信頼できないサーバーまたは安全でないチャネルに送信しないでください。

RippleAPI を使う

アドレス上のグローバル・フリーズを有効または無効にするには、prepareSettings メソッドを使用して Settings トランザクションを準備します。settings パラメータは、次のように設定されたオブジェクトである必要があります:

フィールド 説明
globalFreeze Boolean true to enable a Global Freeze on this address. false to disable Global Freeze.

残りのトランザクションフローは、他のトランザクションと同じです。

アドレス上でグローバル・フリーズを有効にする JavaScript (ECMAScript 6)コードの例:

const {RippleAPI} = require('ripple-lib');

const api = new RippleAPI({
  server: 'wss://s1.ripple.com' // Public rippled server
});
api.on('error', (errorCode, errorMessage) => {
  console.log(errorCode + ': ' + errorMessage);
});

const issuing_address = 'rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn';
const issuing_secret = 's████████████████████████████';
    // Best practice: get your secret from an encrypted
    //  config file instead

api.connect().then(() => {

  // Prepare a settings transaction to enable global freeze
  const settings = {
    'globalFreeze': true
  };

  console.log('preparing settings transaction for account:',
              issuing_address);
  return api.prepareSettings(issuing_address, settings);

}).then(prepared_tx => {

  // Sign and submit the settings transaction
  console.log('signing tx:', prepared_tx.txJSON);
  const signed1 = api.sign(prepared_tx.txJSON, issuing_secret);
  console.log('submitting tx:', signed1.id);

  return api.submit(signed1.signedTransaction);

}).then(() => {
  return api.disconnect();
}).catch(console.error);

ノー・フリーズを有効にする

rippled を使う

アドレス上のノー・フリーズを有効にするには、SetFlag フィールドに asfNoFreeze フラグ値を指定して AccountSet トランザクションを送信します。マスターキーを使用してこのトランザクションに署名する必要があります。一度有効にすると、ノー・フリーズを無効にすることはできません。

WebSocket API を使用してノー・フリーズを有効にする AccountSet トランザクションを送信する例:

WebSocket リクエスト:

{
  "id": 12,
  "command": "submit",
  "tx_json": {
    "TransactionType": "AccountSet",
    "Account": "raKEEVSGnKSD9Zyvxu4z6Pqpm4ABH8FS6n",
    "Fee": "12000",
    "Flags": 0,
    "SetFlag": 6,
    "LastLedgerSequence": 18124917,
    "Sequence": 4
  },
  "secret": "s████████████████████████████",
  "offline": false,
  "fee_mult_max": 1000
}

注意: シークレットキーを信頼できないサーバーまたは安全でないチャネルに送信しないでください。

RippleAPI を使う

アドレス上のノー・フリーズを有効にするには、prepareSettings メソッドを使用して Settings トランザクションを準備します。一度有効にすると、ノー・フリーズを無効にすることはできません。settings パラメータは、次のように設定されたオブジェクトである必要があります:

フィールド 説明
noFreeze Boolean true

マスターキーを使用してこのトランザクションに署名する必要があります。残りのトランザクションフローは、他のトランザクションと同じです。

アドレス上でノー・フリーズを有効にする JavaScript (ECMAScript 6)コードの例:

const {RippleAPI} = require('ripple-lib');

const api = new RippleAPI({
  server: 'wss://s1.ripple.com' // Public rippled server
});
api.on('error', (errorCode, errorMessage) => {
  console.log(errorCode + ': ' + errorMessage);
});

const issuing_address = 'rUpy3eEg8rqjqfUoLeBnZkscbKbFsKXC3v';
const issuing_secret = 'snnDVkSW3aV6jvMJTPdCiE2Qxv1RW';
    // Best practice: get your secret from an encrypted
    //  config file instead

api.connect().then(() => {

  // Prepare a settings transaction to enable no freeze
  const settings = {
    'noFreeze': true
  };

  console.log('preparing settings transaction for account:',
              issuing_address);
  return api.prepareSettings(issuing_address, settings);

}).then(prepared_tx => {

  // Sign and submit the settings transaction
  console.log('signing tx:', prepared_tx.txJSON);
  const signed1 = api.sign(prepared_tx.txJSON, issuing_secret);
  console.log('submitting tx:', signed1.id);

  return api.submit(signed1.signedTransaction);
}).then(() => {
  return api.disconnect();
}).catch(console.error);

個別フリーズを確認する

rippled を使う

トラストラインに個別フリーズが有効になっているかどうかを確認するには、次のパラメータを指定して account_lines メソッドを使用してください:

フィールド 説明
account String The Ripple address of the issuer
peer String The Ripple address of the counterparty
ledger_index String Use validated to get the most recently validated information.

レスポンスには、発行アドレスと取引先がリンクされている通貨ごとに、トラストラインの配列が含まれています。各トラストライン・オブジェクトの次のフィールドを探してください:

フィールド 説明
freeze Boolean (May be omitted) true if the issuing address has frozen this trust line. If omitted, that is the same as false.
freeze_peer Boolean (May be omitted) true if the counterparty has frozen this trust line. If omitted, that is the same as false.

個別フリーズを確認するための WebSocket リクエストの例:

{
  "id": 15,
  "command": "account_lines",
  "account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
  "ledger": "validated",
  "peer": "rsA2LpzuawewSBQXkiju3YQTMzW13pAAdW"
}

WebSocket レスポンスの例:

{
  "id": 15,
  "status": "success",
  "type": "response",
  "result": {
    "account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
    "lines": [
      {
        "account": "rsA2LpzuawewSBQXkiju3YQTMzW13pAAdW",
        "balance": "10",
        "currency": "USD",
        "freeze": true,
        "limit": "110",
        "limit_peer": "0",
        "peer_authorized": true,
        "quality_in": 0,
        "quality_out": 0
      }
    ]
  }
}

フィールド “freeze”: true は、rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn が rsA2LpzuawewSBQXkiju3YQTMzW13pAAdW に対するUSDトラストライン上の個別フリーズを有効にしたことを示します。フィールド “freeze_peer”: true の欠如は、取引先がトラストラインを凍結していないことを示します。

RippleAPI を使う

トラストラインに個別フリーズが有効になっていないかどうかを確認するには、次のパラメータを指定して getTrustlines メソッドを使用してください:

フィールド 説明
address String The Ripple address of the issuer
options.counterparty String The Ripple address of the counterparty

レスポンスには、発行アドレスと取引先がリンクされている通貨ごとに、トラストラインの配列が含まれています。各トラストライン・オブジェクトの次のフィールドを探してください:

フィールド 説明
specification.frozen Boolean (May be omitted) true if the issuing address has frozen the trust line.
counterparty.frozen Boolean (May be omitted) true if the counterparty has frozen the trust line.

トラストラインが凍結されているかどうかを確認するための JavaScript (ECMAScript 6) コードの例:

const {RippleAPI} = require('ripple-lib');

const api = new RippleAPI({
  server: 'wss://s1.ripple.com' // Public rippled server
});
api.on('error', (errorCode, errorMessage) => {
  console.log(errorCode + ': ' + errorMessage);
});

const my_address = 'rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn';
const counterparty_address = 'rUpy3eEg8rqjqfUoLeBnZkscbKbFsKXC3v';
const frozen_currency = 'USD';

api.connect().then(() => {

  // Look up current state of trust line
  const options = {counterparty: counterparty_address,
                   currency: frozen_currency};
  console.log('looking up', frozen_currency, 'trust line from',
              my_address, 'to', counterparty_address);
  return api.getTrustlines(my_address, options);

}).then(data => {

  if (data.length !== 1) {
    throw 'should only be 1 trust line per counterparty+currency pair';
  }

  const trustline = data[0];
  console.log('Trust line frozen from our side?',
              trustline.specification.frozen === true);
  console.log('Trust line frozen from counterparty\'s side?',
              trustline.counterparty.frozen === true);

}).then(() => {
  return api.disconnect();
}).catch(console.error);

グローバル・フリーズとノー・フリーズを確認する

rippled を使う

アドレスでグローバル・フリーズ、ノー・フリーズ、またはその両方が有効になっているかどうかを確認するには、account_info メソッドを次のパラメータとともに使用してください:

フィールド 説明
account String The Ripple address of the issuing address
ledger_index String Use validated to get the most recently validated information.

bitwise-AND オペレータを使用して、レスポンスの account_data.Flags フィールドの値を確認してください:

  • Flags AND 0x00400000 (lsfGlobalFreeze) がゼロ以外の場合: グローバル・フリーズが有効。
  • Flags AND 0x00200000 (lsfNoFreeze) がゼロ以外の場合: ノー・フリーズが有効。

WebSocket リクエストの例:

{
  "id": 1,
  "command": "account_info",
  "account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
  "ledger_index": "validated"
}

WebSocket レスポンス:

{
  "id": 4,
  "status": "success",
  "type": "response",
  "result": {
    "account_data": {
      "Account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
      "AccountTxnID": "41320138CA9837B34E82B3B3D6FB1E581D5DE2F0A67B3D62B5B8A8C9C8D970D0",
      "Balance": "100258663",
      "Domain": "6D64756F31332E636F6D",
      "EmailHash": "98B4375E1D753E5B91627516F6D70977",
      "Flags": 12582912,
      "LedgerEntryType": "AccountRoot",
      "MessageKey": "0000000000000000000000070000000300",
      "OwnerCount": 4,
      "PreviousTxnID": "41320138CA9837B34E82B3B3D6FB1E581D5DE2F0A67B3D62B5B8A8C9C8D970D0",
      "PreviousTxnLgrSeq": 18123095,
      "Sequence": 352,
      "TransferRate": 1004999999,
      "index": "13F1A95D7AAB7108D5CE7EEAF504B2894B8C674E6D68499076441C4837282BF8",
      "urlgravatar": "http://www.gravatar.com/avatar/98b4375e1d753e5b91627516f6d70977"
    },
    "ledger_hash": "A777B05A293A73E511669B8A4A45A298FF89AD9C9394430023008DB4A6E7FDD5",
    "ledger_index": 18123249,
    "validated": true
  }
}

上記の例では、Flags の値は 12582912 です。これは、次の JavaScript コードで実演されるように、次のフラグが有効であることを示します: lsfGlobalFreeze, lsfDefaultRipple

var lsfGlobalFreeze = 0x00400000;
var lsfNoFreeze = 0x00200000;

var currentFlags = 12582912;

console.log(currentFlags & lsfGlobalFreeze); //4194304
//therefore, Global Freeze is enabled

console.log(currentFlags & lsfNoFreeze); //0
//therefore, No Freeze is not enabled

RippleAPI を使う

アドレスでグローバル・フリーズ、ノー・フリーズ、またはその両方が有効になっているかどうかを確認するには、次のパラメータを指定して getSettings メソッドを使用してください:

フィールド 説明
address String The Ripple address of the issuing address

レスポンス・オブジェクトの次の値を探してください:

フィールド 説明
noFreeze Boolean (May be omitted) true if No Freeze is enabled.
globalFreeze Boolean (May be omitted) true if Global Freeze is enabled.

アドレスでグローバル・フリーズまたはノー・フリーズが有効かどうかを確認するための JavaScript (ECMAScript 6) コードの例:

const {RippleAPI} = require('ripple-lib');

const api = new RippleAPI({
  server: 'wss://s1.ripple.com' // Public rippled server
});
api.on('error', (errorCode, errorMessage) => {
  console.log(errorCode + ': ' + errorMessage);
});

const my_address = 'rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn';

api.connect().then(() => {
  // Look up settings object
  return api.getSettings(my_address);
}).then(settings => {
  console.log('Got settings for address', my_address);
  console.log('Global Freeze enabled?',
              (settings.globalFreeze === true));
  console.log('No Freeze enabled?', (settings.noFreeze === true));

}).then(() => {
  return api.disconnect();
}).catch(console.error);

関連項目