第三者の仲介者が入ることなく、異なるブロックチェーン間でトークンの交換をします。
Alice と Bob は 10 alice.tokens を 10 bob.tokens に交換しようとしています。課題は彼らが同じネットワークに存在していないことです: alice:token は Symbol のプライベートチェーン上に、一方で bob:token は Symbol のパブリックチェーン上に存在しています。
非アトミックな解決方法の場合:
Alice が 10 alice:tokens を Bob へ送信する (プライベートチェーン)
Bob はトランザクションを受信する
Bob が 10 bob:tokens を Alice へ送信する (パブリックチェーン)
Alice はトランザクションを受信する
しかし、彼らはそれほどお互いを信頼しあってはいません。お気づきでしょうが、 Bob は 3 を実行しない場合に Alice's のトークンを保持できます。
このガイドでは、さまざまな参加者とネットワーク間でトークンを安全に交換する定義をする方法を示します。
入門セクション を完了している
スワップに関与するすべての参加者は、各ブロックチェーンで少なくとも 1 つのアカウントを所有している必要があります。
const alicePublicChainAccount = Account.createFromPrivateKey(
'',
NetworkType.MAIN_NET,
);
const alicePrivateChainAccount = Account.createFromPrivateKey(
'',
NetworkType.MIJIN,
);
const bobPublicChainAccount = Account.createFromPrivateKey(
'',
NetworkType.MAIN_NET,
);
const bobPrivateChainAccount = Account.createFromPrivateKey(
'',
NetworkType.MIJIN,
);
const privateChainTransactionHttp = new TransactionHttp(
'http://localhost:3000',
);
const publicChainTransactionHttp = new TransactionHttp('http://localhost:3000');
const publicChainGenerationHash = process.env.NETWORK_GENERATION_HASH as string;
const privateChainGenerationHash = process.env
.NETWORK_GENERATION_HASH as string;
const alicePublicChainAccount = symbol_sdk_1.Account.createFromPrivateKey(
'',
symbol_sdk_1.NetworkType.MAIN_NET,
);
const alicePrivateChainAccount = symbol_sdk_1.Account.createFromPrivateKey(
'',
symbol_sdk_1.NetworkType.MIJIN,
);
const bobPublicChainAccount = symbol_sdk_1.Account.createFromPrivateKey(
'',
symbol_sdk_1.NetworkType.MAIN_NET,
);
const bobPrivateChainAccount = symbol_sdk_1.Account.createFromPrivateKey(
'',
symbol_sdk_1.NetworkType.MIJIN,
);
const privateChainTransactionHttp = new symbol_sdk_1.TransactionHttp(
'http://localhost:3000',
);
const publicChainTransactionHttp = new symbol_sdk_1.TransactionHttp(
'http://localhost:3000',
);
const publicChainGenerationHash = process.env.NETWORK_GENERATION_HASH;
const privateChainGenerationHash = process.env.NETWORK_GENERATION_HASH;
Alice のアカウントはプライベートチェーン上で最低でも 10 alice.tokens を保有している必要があります。
Bob のアカウントはパブリックチェーン上で最低でも 10 bob.tokens を保有している必要があります。
両方のアカウントは手数料を支払うために十分な手数料が必要です。
1. Alice generates a random set of bytes called proof
. The proof should have a size between 10
and 1000
bytes.
Then, applies a SHA3-256 algorithm to it, obtaining the secret
.
Alice は得られた proof を 利用可能なアルゴリズム の1つでハッシュ化して secret
を生成します。
const random = crypto.randomBytes(20);
const proof = random.toString('hex');
console.log('Proof:', proof);
const hash = sha3_256.create();
const secret = hash.update(random).hex().toUpperCase();
console.log('Secret:', secret);
const random = crypto.randomBytes(20);
const proof = random.toString('hex');
console.log('Proof:', proof);
const hash = js_sha3_1.sha3_256.create();
const secret = hash.update(random).hex().toUpperCase();
console.log('Secret:', secret);
Alice は SecretLockTransaction TX1 を定義します:
TX1 Property |
Value |
---|---|
Type |
SecretLockTransaction |
Mosaic |
10 |
Recipient |
Bob のアドレス (プライベートチェーン) |
Algorithm |
SHA3-256 |
Duration |
96 h |
Secret |
SHA3-256(proof) |
Network |
Private Chain |
const tx1 = SecretLockTransaction.create(
Deadline.create(epochAdjustment),
new Mosaic(new MosaicId('00D3378709746FC4'), UInt64.fromUint(10)),
UInt64.fromUint((96 * 3600) / 30), // assuming one block every 30 seconds
LockHashAlgorithm.Op_Sha3_256,
secret,
bobPrivateChainAccount.address,
NetworkType.MIJIN,
);
const tx1 = symbol_sdk_1.SecretLockTransaction.create(
symbol_sdk_1.Deadline.create(epochAdjustment),
new symbol_sdk_1.Mosaic(
new symbol_sdk_1.MosaicId('00D3378709746FC4'),
symbol_sdk_1.UInt64.fromUint(10),
),
symbol_sdk_1.UInt64.fromUint((96 * 3600) / 30), // assuming one block every 30 seconds
symbol_sdk_1.LockHashAlgorithm.Op_Sha3_256,
secret,
bobPrivateChainAccount.address,
symbol_sdk_1.NetworkType.MIJIN,
);
度アナウンスされると、誰かがシークレットにマッチする証明を発見するまで、このトランザクションはロックされたままです。もしセットされた期限よりも前に、誰もアンロックしない場合は、ロックされた資産は Alice へ返還されます。
Alice は TX1 をプライベートネットワークへアナウンス し Bob とシークレットを共有 します。
注釈
Bob はチェーンからシークレットを取得する必要があります。シークレットの正当性を検証するのは Bob の責任です。
const tx1Signed = alicePrivateChainAccount.sign(
tx1,
privateChainGenerationHash,
);
privateChainTransactionHttp.announce(tx1Signed).subscribe(
(x) => console.log(x),
(err) => console.error(err),
);
const tx1Signed = alicePrivateChainAccount.sign(
tx1,
privateChainGenerationHash,
);
privateChainTransactionHttp.announce(tx1Signed).subscribe(
(x) => console.log(x),
(err) => console.error(err),
);
Bob は以下の SecretLockTransaction TX2 を パブリックネットワーク へアナウンスします
TX2 Property |
Value |
---|---|
Type |
SecretLockTransaction |
Mosaic |
10 |
Recipient |
Alice のアドレス (パブリックチェーン) |
Algorithm |
SHA3-256 |
Duration |
84 h |
Secret |
SHA3-256(proof) |
Network |
Public Chain |
const tx2 = SecretLockTransaction.create(
Deadline.create(epochAdjustment),
new Mosaic(new MosaicId('10293DE77C684F71'), UInt64.fromUint(10)),
UInt64.fromUint((84 * 3600) / 30), // assuming one block every 30 seconds
LockHashAlgorithm.Op_Sha3_256,
secret,
alicePublicChainAccount.address,
NetworkType.MAIN_NET,
UInt64.fromUint(2000000),
);
const tx2 = symbol_sdk_1.SecretLockTransaction.create(
symbol_sdk_1.Deadline.create(epochAdjustment),
new symbol_sdk_1.Mosaic(
new symbol_sdk_1.MosaicId('10293DE77C684F71'),
symbol_sdk_1.UInt64.fromUint(10),
),
symbol_sdk_1.UInt64.fromUint((84 * 3600) / 30), // assuming one block every 30 seconds
symbol_sdk_1.LockHashAlgorithm.Op_Sha3_256,
secret,
alicePublicChainAccount.address,
symbol_sdk_1.NetworkType.MAIN_NET,
symbol_sdk_1.UInt64.fromUint(2000000),
);
注釈
資産をアンロックできる時間は、TX1 のタイムフレームよりも短くする必要があります。Alice はシークレットを知っていて、Bob はそれを確信しているので、Alice がシークレットを公開した後に、彼にはいくぶんかの時間があるでしょう。
注釈
TX1 が ロールバック しないことを保証するために、Bob は TX2 をアナウンスする前に、 TX1 の少なくとも maxRollBackBlocks
承認まで待つ必要があります。
const tx2Signed = bobPublicChainAccount.sign(tx2, publicChainGenerationHash);
publicChainTransactionHttp.announce(tx2Signed).subscribe(
(x) => console.log(x),
(err) => console.error(err),
);
const tx2Signed = bobPublicChainAccount.sign(tx2, publicChainGenerationHash);
publicChainTransactionHttp.announce(tx2Signed).subscribe(
(x) => console.log(x),
(err) => console.error(err),
);
Alice は SecretProofTransaction TX3 を パブリックネットワーク へアナウンスします。このトランザクションは使用している暗号化アルゴリズム、オリジナルの証明とシークレットを定義します。
TX3 Property |
Value |
---|---|
Type |
SecretProofTransaction |
Recipient |
Alice のアドレス (パブリックチェーン) |
Algorithm |
SHA3-256 |
Secret |
SHA3-256(proof) |
Proof |
proof |
Network |
Public Chain |
注釈
TX2 が ロールバック しないことを保証するために、Bob は TX3 をアナウンスする前に、 TX2 の少なくとも maxRollBackBlocks
承認まで待つ必要があります。
const tx3 = SecretProofTransaction.create(
Deadline.create(epochAdjustment),
LockHashAlgorithm.Op_Sha3_256,
secret,
alicePublicChainAccount.address,
proof,
NetworkType.MAIN_NET,
UInt64.fromUint(2000000),
);
const tx3Signed = alicePublicChainAccount.sign(tx3, publicChainGenerationHash);
publicChainTransactionHttp.announce(tx3Signed).subscribe(
(x) => console.log(x),
(err) => console.error(err),
);
const tx3 = symbol_sdk_1.SecretProofTransaction.create(
symbol_sdk_1.Deadline.create(epochAdjustment),
symbol_sdk_1.LockHashAlgorithm.Op_Sha3_256,
secret,
alicePublicChainAccount.address,
proof,
symbol_sdk_1.NetworkType.MAIN_NET,
symbol_sdk_1.UInt64.fromUint(2000000),
);
const tx3Signed = alicePublicChainAccount.sign(tx3, publicChainGenerationHash);
publicChainTransactionHttp.announce(tx3Signed).subscribe(
(x) => console.log(x),
(err) => console.error(err),
);
TX3 が承認されると proof が明かされます。TX2 トランザクションはアンロック されて Alice はロックされた資産を受け取ります。
Bob は proof を手に入れて SecretProofTransaction TX4 を プライベートネットワーク へアナウンスし、ロックされた資産を TX1 から受け取ります。
注釈
TX3 が ロールバック しないことを保証するために、Bob は TX4 をアナウンスする前に、 TX3 の少なくとも maxRollBackBlocks
承認まで待つ必要があります。
TX4 Property |
Value |
---|---|
Type |
SecretProofTransaction |
Recipient |
Bob のアドレス (プライベートチェーン) |
Algorithm |
SHA3-256 |
Secret |
SHA3-256(proof) |
Proof |
proof |
Network |
Private Chain |
const tx4 = SecretProofTransaction.create(
Deadline.create(epochAdjustment),
LockHashAlgorithm.Op_Sha3_256,
secret,
bobPrivateChainAccount.address,
proof,
NetworkType.MIJIN,
);
const tx4Signed = bobPrivateChainAccount.sign(tx4, privateChainGenerationHash);
privateChainTransactionHttp.announce(tx4Signed).subscribe(
(x) => console.log(x),
(err) => console.error(err),
);
const tx4 = symbol_sdk_1.SecretProofTransaction.create(
symbol_sdk_1.Deadline.create(epochAdjustment),
symbol_sdk_1.LockHashAlgorithm.Op_Sha3_256,
secret,
bobPrivateChainAccount.address,
proof,
symbol_sdk_1.NetworkType.MIJIN,
);
const tx4Signed = bobPrivateChainAccount.sign(tx4, privateChainGenerationHash);
privateChainTransactionHttp.announce(tx4Signed).subscribe(
(x) => console.log(x),
(err) => console.error(err),
);
このプロセスはアトミックですが、デッドラインを迎える前に完了するまで、多くの時間がかかることになります:
✅ Bob は TX2 をアナウンスしたくありません: Alice は 94 時間後に彼の資産の返還を受信します。
✅ Alice は TX3 をアナウンスしません: Bob は 84 時間後に彼の資産の返還を受取ります。Alice は同様に 94 時間後に彼女の資産をアンロックします。
⚠️ Alice は TX3 に署名しアナウンスします: Alice は Bob の資産を受取ります: Bob は TX1 の正当性が TX2 よりも長いため、Bob は TX4 に署名する十分な時間があります。
⚠️ロールバックは歴史を書き換えます: Alice と Bob それぞれのトランザクションの承認を最低でも maxRollBackBlocks
を待ちます。