# 条件に基づくEscrowの送信 ## 1.条件とフルフィルメントの生成 XRP Ledger EscrowにはPREIMAGE-SHA-256 [Crypto-Conditions](https://tools.ietf.org/html/draft-thomas-crypto-conditions-03)が必要です。条件とフルフィルメントを適切なフォーマットで計算するには、[five-bells-condition](https://github.com/interledgerjs/five-bells-condition)などのCrypto-conditionsライブラリを使用する必要があります。フルフィルメントについては、以下のフルフィルメントを生成するためのメソッドのいずれかを使用することが推奨されます。 - 暗号論的に安全な乱数ソースを使用して、32バイト以上のランダムバイトを生成します。 - Interledger Protocolの[PSK仕様](https://github.com/interledger/rfcs/blob/master/deprecated/0016-pre-shared-key/0016-pre-shared-key.md)に従い、ILPパケットのHMAC-SHA-256をフルフィルメントとして使用します。 ランダムなフルフィルメントと条件のJavaScriptコードの例: ```js const cc = require('five-bells-condition') const crypto = require('crypto') const preimageData = crypto.randomBytes(32) const myFulfillment = new cc.PreimageSha256() myFulfillment.setPreimage(preimageData) const condition = myFulfillment.getConditionBinary().toString('hex').toUpperCase() console.log('Condition:', condition) // (Random hexadecimal, 72 chars in length) // keep secret until you want to finish executing the held payment: const fulfillment = myFulfillment.serializeBinary().toString('hex').toUpperCase() console.log('Fulfillment:', fulfillment) // (Random hexadecimal, 78 chars in length) ``` 後で使用できるように条件とフルフィルメントを保存します。保留中の支払いの実行が完了するまでは、フルフィルメントを公開しないでください。フルフィルメントを知っていれば誰でもEscrowを終了でき、保留中の資金を指定された送金先にリリースできます。 ## 2.リリース時刻または取消し時刻の計算 条件付き`Escrow`トランザクションには、`CancelAfter`フィールドと`FinishAfter`フィールドのいずれか、または両方が含まれている必要があります。`CancelAfter`フィールドを使用すると、指定の時刻までに条件を満たすことができなかった場合に送金元へXRPを返金できます。`FinishAfter`フィールドに指定される時刻より前の時間は、正しいフルフィルメントが送信されてもEscrowを実行できません。いずれのフィールドでも、将来の時刻を指定する必要があります。 `CancelAfter`の時刻を24時間先に設定する例: JavaScript ```js const rippleOffset = 946684800 const CancelAfter = Math.floor(Date.now() / 1000) + (24*60*60) - rippleOffset console.log(CancelAfter) // Example:556927412 ``` Python 2/3 ```python from time import time ripple_offset = 946684800 cancel_after = int(time()) + (24*60*60) - 946684800 print(cancel_after) # Example: 556927412 ``` XRP Ledgerでは、時刻を**Rippleエポック(2000-01-01T00:00:00Z)以降の経過秒数**として指定する必要があります。`CancelAfter`または`FinishAfter`フィールドで、UNIX時刻を同等のRipple時刻に変換せずに使用すると、ロック解除時刻が**30年**先に設定されることになります。 ## 3.EscrowCreateトランザクションの送信 [EscrowCreateトランザクション](/ja/docs/references/protocol/transactions/types/escrowcreate)に[署名して送信](/ja/docs/concepts/transactions#%E3%83%88%E3%83%A9%E3%83%B3%E3%82%B6%E3%82%AF%E3%82%B7%E3%83%A7%E3%83%B3%E3%81%B8%E3%81%AE%E7%BD%B2%E5%90%8D%E3%81%A8%E3%83%88%E3%83%A9%E3%83%B3%E3%82%B6%E3%82%AF%E3%82%B7%E3%83%A7%E3%83%B3%E3%81%AE%E9%80%81%E4%BF%A1)します。トランザクションの`Condition`フィールドを、保留中の支払いがリリースされる時刻に設定します。`Destination`を受取人に設定します。受取人と送金元のアドレスは同じでもかまいません。前の手順で算出した`CancelAfter`または`FinishAfter`の時刻も指定します。`Amount`を、Escrowする[XRPのdrop数](/ja/docs/references/protocol/data-types/basic-data-types#%E9%80%9A%E8%B2%A8%E9%A1%8D%E3%81%AE%E6%8C%87%E5%AE%9A)の合計額に設定します。 注意 自分が管理していないサーバに秘密鍵を送信しないでください。暗号化されていない秘密鍵をネットワーク経由で送信しないでください。 リクエスト: Websocket { "id": 1, "command": "submit", "secret": "s████████████████████████████", "tx_json": { "Account": "rEhw9vD98ZrkY4tZPvkZst5H18RysqFdaB", "TransactionType": "EscrowCreate", "Amount": "100000", "Destination": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", "Condition": "A0258020E24D9E1473D4DF774F6D8E089067282034E4FA7ECACA2AD2E547953B2C113CBD810120", "CancelAfter": 556927412 } } レスポンス: Websocket { "id": 1, "status": "success", "type": "response", "result": { "engine_result": "tesSUCCESS", "engine_result_code": 0, "engine_result_message": "The transaction was applied. Only final in a validated ledger.", "tx_blob": "120001228000000024000000052024213209B46140000000000186A068400000000000000A732103E498E35BC1E109C5995BD3AB0A6D4FFAB61B853C8F6010FABC5DABAF34478B61744730450221008AC8BDC2151D5EF956197F0E6E89A4F49DEADC1AC38367870E444B1EA8D88D97022075E31427B455DFF87F0F22B849C71FC3987A91C19D63B6D0242E808347EC8A8F701127A0258020E24D9E1473D4DF774F6D8E089067282034E4FA7ECACA2AD2E547953B2C113CBD81012081149A2AA667E1517EFA8A6B552AB2EDB859A99F26B283144B4E9C06F24296074F7BC48F92A97916C6DC5EA9", "tx_json": { "Account": "rEhw9vD98ZrkY4tZPvkZst5H18RysqFdaB", "Amount": "100000", "CancelAfter": 556927412, "Condition": "A0258020E24D9E1473D4DF774F6D8E089067282034E4FA7ECACA2AD2E547953B2C113CBD810120", "Destination": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", "Fee": "10", "Flags": 2147483648, "Sequence": 5, "SigningPubKey": "03E498E35BC1E109C5995BD3AB0A6D4FFAB61B853C8F6010FABC5DABAF34478B61", "TransactionType": "EscrowCreate", "TxnSignature": "30450221008AC8BDC2151D5EF956197F0E6E89A4F49DEADC1AC38367870E444B1EA8D88D97022075E31427B455DFF87F0F22B849C71FC3987A91C19D63B6D0242E808347EC8A8F", "hash": "E22D1F6EB006CAD35E0DBD3B4F3748427055E4C143EBE95AA6603823AEEAD324" } } } ## 4.検証の待機 本番環境のネットワークやTestnetでは、レジャーが自動的に閉鎖するまでに4~7秒かかる場合があります。 スタンドアロンモードで`rippled`を実行している場合は、[ledger_acceptメソッド][]を使用してレジャーを手動で閉鎖します。 ## 5.Escrowが作成されたことの確認 トランザクションの識別用ハッシュを指定した[txメソッド](/ja/docs/references/http-websocket-apis/public-api-methods/transaction-methods/tx)を使用して、トランザクションの最終ステータスを確認します。特に、[Escrowレジャーオブジェクト](/ja/docs/concepts/payment-types/escrow)が作成されたことを示す`CreatedNode`をトランザクションメタデータで探します。 リクエスト: Websocket { "id": 3, "command": "tx", "transaction": "E22D1F6EB006CAD35E0DBD3B4F3748427055E4C143EBE95AA6603823AEEAD324" } レスポンス: Websocket { "id": 3, "status": "success", "type": "response", "result": { "Account": "rEhw9vD98ZrkY4tZPvkZst5H18RysqFdaB", "Amount": "100000", "CancelAfter": 556927412, "Condition": "A0258020E24D9E1473D4DF774F6D8E089067282034E4FA7ECACA2AD2E547953B2C113CBD810120", "Destination": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", "Fee": "10", "Flags": 2147483648, "Sequence": 5, "SigningPubKey": "03E498E35BC1E109C5995BD3AB0A6D4FFAB61B853C8F6010FABC5DABAF34478B61", "TransactionType": "EscrowCreate", "TxnSignature": "30450221008AC8BDC2151D5EF956197F0E6E89A4F49DEADC1AC38367870E444B1EA8D88D97022075E31427B455DFF87F0F22B849C71FC3987A91C19D63B6D0242E808347EC8A8F", "date": 556841101, "hash": "E22D1F6EB006CAD35E0DBD3B4F3748427055E4C143EBE95AA6603823AEEAD324", "inLedger": 1772019, "ledger_index": 1772019, "meta": { "AffectedNodes": [ { "ModifiedNode": { "LedgerEntryType": "AccountRoot", "LedgerIndex": "13F1A95D7AAB7108D5CE7EEAF504B2894B8C674E6D68499076441C4837282BF8", "PreviousTxnID": "52C4F626FE6F33699B6BE8ADF362836DDCE9B0B1294BFAA15D65D61501350BE6", "PreviousTxnLgrSeq": 1771204 } }, { "ModifiedNode": { "FinalFields": { "Flags": 0, "Owner": "rEhw9vD98ZrkY4tZPvkZst5H18RysqFdaB", "RootIndex": "4B4EBB6D8563075813D47491CC325865DFD3DC2E94889F0F39D59D9C059DD81F" }, "LedgerEntryType": "DirectoryNode", "LedgerIndex": "4B4EBB6D8563075813D47491CC325865DFD3DC2E94889F0F39D59D9C059DD81F" } }, { "ModifiedNode": { "FinalFields": { "Account": "rEhw9vD98ZrkY4tZPvkZst5H18RysqFdaB", "Balance": "9999798970", "Flags": 0, "OwnerCount": 1, "Sequence": 6 }, "LedgerEntryType": "AccountRoot", "LedgerIndex": "5F3B7107F4B524367A173A2B0EAB66E8CC4D2178C1B0C0528CB2F73A8B6BF254", "PreviousFields": { "Balance": "9999898980", "OwnerCount": 0, "Sequence": 5 }, "PreviousTxnID": "52C4F626FE6F33699B6BE8ADF362836DDCE9B0B1294BFAA15D65D61501350BE6", "PreviousTxnLgrSeq": 1771204 } }, { "CreatedNode": { "LedgerEntryType": "Escrow", "LedgerIndex": "E2CF730A31FD419382350C9DBD8DB7CD775BA5AA9B97A9BE9AB07304AA217A75", "NewFields": { "Account": "rEhw9vD98ZrkY4tZPvkZst5H18RysqFdaB", "Amount": "100000", "CancelAfter": 556927412, "Condition": "A0258020E24D9E1473D4DF774F6D8E089067282034E4FA7ECACA2AD2E547953B2C113CBD810120", "Destination": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn" } } } ], "TransactionIndex": 0, "TransactionResult": "tesSUCCESS" }, "validated": true } } ## 6.EscrowFinishトランザクションの送信 `FinishAfter`の時刻が経過した後で資金のリリースを実行する[EscrowFinishトランザクション](/ja/docs/references/protocol/transactions/types/escrowfinish)に[署名して送信](/ja/docs/concepts/transactions#%E3%83%88%E3%83%A9%E3%83%B3%E3%82%B6%E3%82%AF%E3%82%B7%E3%83%A7%E3%83%B3%E3%81%B8%E3%81%AE%E7%BD%B2%E5%90%8D%E3%81%A8%E3%83%88%E3%83%A9%E3%83%B3%E3%82%B6%E3%82%AF%E3%82%B7%E3%83%A7%E3%83%B3%E3%81%AE%E9%80%81%E4%BF%A1)します。トランザクションの`Owner`フィールドにEscrowCreateトランザクションの`Account`アドレスを設定し、`OfferSequence` にEscrowCreateトランザクションの`Sequence`番号を設定します。`Condition`フィールドと`Fulfillment`フィールドに、ステップ1で生成した条件値とフルフィルメント値をそれぞれ16進数で設定します。フルフィルメントのサイズ(バイト数)に基づいて`Fee`([トランザクションコスト](/ja/docs/concepts/transactions/transaction-cost))の値を設定します。条件付きEscrowFinishでは、少なくとも330 drop(XRP)と、フルフィルメントのサイズで16バイトごとに10 dropが必要です。 EscrowCreateトランザクションに`FinishAfter`フィールドが含まれている場合、Escrowの条件として正しいフルフィルメントを指定しても、この時刻よりも前の時点ではこのトランザクションを実行できません。前に閉鎖されたレジャーの閉鎖時刻が`FinishAfter`の時刻よりも前である場合、EscrowFinishトランザクションは[結果コード](/ja/docs/references/protocol/transactions/transaction-results)`tecNO_PERMISSION`で失敗します。 Escrowが有効期限切れの場合は、[Escrowの取消し](/ja/docs/tutorials/how-tos/use-specialized-payment-types/use-escrows/cancel-an-expired-escrow)だけが可能です。 注意 自分が管理していないサーバに秘密鍵を送信しないでください。暗号化されていない秘密鍵をネットワーク経由で送信しないでください。 Websocket { "id": 4, "command": "submit", "secret": "s████████████████████████████", "tx_json": { "Account": "rEhw9vD98ZrkY4tZPvkZst5H18RysqFdaB", "TransactionType": "EscrowFinish", "Owner": "rEhw9vD98ZrkY4tZPvkZst5H18RysqFdaB", "OfferSequence": 5, "Condition": "A0258020E24D9E1473D4DF774F6D8E089067282034E4FA7ECACA2AD2E547953B2C113CBD810120", "Fulfillment": "A0228020D280D1A02BAD0D2EBC0528B92E9BF37AC3E2530832C2C52620307135156F1048", "Fee": "500" } } レスポンス: Websocket { "id": 4, "status": "success", "type": "response", "result": { "engine_result": "tesSUCCESS", "engine_result_code": 0, "engine_result_message": "The transaction was applied. Only final in a validated ledger.", "tx_blob": "120002228000000024000000062019000000056840000000000001F4732103E498E35BC1E109C5995BD3AB0A6D4FFAB61B853C8F6010FABC5DABAF34478B617446304402207DE4EA9C8655E75BA01F96345B3F62074313EB42C15D9C4871E30F02202D2BA50220070E52AD308A31AC71E33BA342F31B68D1D1B2A7A3A3ED6E8552CA3DCF14FBB2701024A0228020D280D1A02BAD0D2EBC0528B92E9BF37AC3E2530832C2C52620307135156F1048701127A0258020E24D9E1473D4DF774F6D8E089067282034E4FA7ECACA2AD2E547953B2C113CBD81012081149A2AA667E1517EFA8A6B552AB2EDB859A99F26B282149A2AA667E1517EFA8A6B552AB2EDB859A99F26B2", "tx_json": { "Account": "rEhw9vD98ZrkY4tZPvkZst5H18RysqFdaB", "Condition": "A0258020E24D9E1473D4DF774F6D8E089067282034E4FA7ECACA2AD2E547953B2C113CBD810120", "Fee": "500", "Flags": 2147483648, "Fulfillment": "A0228020D280D1A02BAD0D2EBC0528B92E9BF37AC3E2530832C2C52620307135156F1048", "OfferSequence": 5, "Owner": "rEhw9vD98ZrkY4tZPvkZst5H18RysqFdaB", "Sequence": 6, "SigningPubKey": "03E498E35BC1E109C5995BD3AB0A6D4FFAB61B853C8F6010FABC5DABAF34478B61", "TransactionType": "EscrowFinish", "TxnSignature": "304402207DE4EA9C8655E75BA01F96345B3F62074313EB42C15D9C4871E30F02202D2BA50220070E52AD308A31AC71E33BA342F31B68D1D1B2A7A3A3ED6E8552CA3DCF14FBB2", "hash": "0E88368CAFC69A722ED829FAE6E2DD3575AE9C192691E60B5ACDF706E219B2BF" } } } トランザクションの識別用`hash`値をメモしておきます。これにより、検証済みレジャーバージョンに記録されるときにその最終ステータスを確認できます。 ## 7.検証の待機 本番環境のネットワークやTestnetでは、レジャーが自動的に閉鎖するまでに4~7秒かかる場合があります。 スタンドアロンモードで`rippled`を実行している場合は、[ledger_acceptメソッド][]を使用してレジャーを手動で閉鎖します。 ## 8.最終結果の確認 EscrowFinishトランザクションの識別用ハッシュを指定した[txメソッド](/ja/docs/references/http-websocket-apis/public-api-methods/transaction-methods/tx)を使用して、トランザクションの最終ステータスを確認します。特にトランザクションメタデータ内で、エスクローに預託された支払いの送金先の`ModifiedNode`(タイプが`AccountRoot`)を確認します。オブジェクトの`FinalFields`に、`Balance`フィールドのXRP返金額の増分が表示されている必要があります。 リクエスト: { "id": 20, "command": "tx", "transaction": "0E88368CAFC69A722ED829FAE6E2DD3575AE9C192691E60B5ACDF706E219B2BF" } レスポンス: { "id": 20, "status": "success", "type": "response", "result": { "Account": "rEhw9vD98ZrkY4tZPvkZst5H18RysqFdaB", "Condition": "A0258020E24D9E1473D4DF774F6D8E089067282034E4FA7ECACA2AD2E547953B2C113CBD810120", "Fee": "500", "Flags": 2147483648, "Fulfillment": "A0228020D280D1A02BAD0D2EBC0528B92E9BF37AC3E2530832C2C52620307135156F1048", "OfferSequence": 2, "Owner": "rEhw9vD98ZrkY4tZPvkZst5H18RysqFdaB", "Sequence": 4, "SigningPubKey": "03E498E35BC1E109C5995BD3AB0A6D4FFAB61B853C8F6010FABC5DABAF34478B61", "TransactionType": "EscrowFinish", "TxnSignature": "3045022100925FEBE21C2E57F81C472A4E5869CAB1D0164C472A46532F39F6F9F7ED6846D002202CF9D9063ADC4CC0ADF4C4692B7EE165C5D124CAA855649389E245D993F41D4D", "date": 556838610, "hash": "0E88368CAFC69A722ED829FAE6E2DD3575AE9C192691E60B5ACDF706E219B2BF", "inLedger": 1771204, "ledger_index": 1771204, "meta": { "AffectedNodes": [ { "ModifiedNode": { "FinalFields": { "Account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", "Balance": "400100000", "Flags": 0, "OwnerCount": 0, "Sequence": 1 }, "LedgerEntryType": "AccountRoot", "LedgerIndex": "13F1A95D7AAB7108D5CE7EEAF504B2894B8C674E6D68499076441C4837282BF8", "PreviousFields": { "Balance": "400000000" }, "PreviousTxnID": "795CBC8AFAAB9DC7BD9944C7FAEABF9BB0802A84520BC649213AD6A2C3256C95", "PreviousTxnLgrSeq": 1770775 } }, { "ModifiedNode": { "FinalFields": { "Flags": 0, "Owner": "rEhw9vD98ZrkY4tZPvkZst5H18RysqFdaB", "RootIndex": "4B4EBB6D8563075813D47491CC325865DFD3DC2E94889F0F39D59D9C059DD81F" }, "LedgerEntryType": "DirectoryNode", "LedgerIndex": "4B4EBB6D8563075813D47491CC325865DFD3DC2E94889F0F39D59D9C059DD81F" } }, { "ModifiedNode": { "FinalFields": { "Account": "rEhw9vD98ZrkY4tZPvkZst5H18RysqFdaB", "Balance": "9999898980", "Flags": 0, "OwnerCount": 0, "Sequence": 5 }, "LedgerEntryType": "AccountRoot", "LedgerIndex": "5F3B7107F4B524367A173A2B0EAB66E8CC4D2178C1B0C0528CB2F73A8B6BF254", "PreviousFields": { "Balance": "9999899480", "OwnerCount": 1, "Sequence": 4 }, "PreviousTxnID": "5C2A1E7B209A7404D3722A010D331A8C1C853109A47DDF620DE5E3D59F026581", "PreviousTxnLgrSeq": 1771042 } }, { "DeletedNode": { "FinalFields": { "Account": "rEhw9vD98ZrkY4tZPvkZst5H18RysqFdaB", "Amount": "100000", "Condition": "A0258020E24D9E1473D4DF774F6D8E089067282034E4FA7ECACA2AD2E547953B2C113CBD810120", "Destination": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", "FinishAfter": 556838185, "Flags": 0, "OwnerNode": "0000000000000000", "PreviousTxnID": "795CBC8AFAAB9DC7BD9944C7FAEABF9BB0802A84520BC649213AD6A2C3256C95", "PreviousTxnLgrSeq": 1770775 }, "LedgerEntryType": "Escrow", "LedgerIndex": "DC524D17B3F650E7A215B332F418E54AE59B0DFC5392E74958B0037AFDFE8C8D" } } ], "TransactionIndex": 1, "TransactionResult": "tesSUCCESS" }, "validated": true } }