Intercambia tokens entre diferentes cadenas de bloques sin usar una parte intermediaria en el proceso.
Alice y Bob desean intercambiar 10 tokens de Alice por 10 tokens de Bob. El problema es que no están en la misma red: el token de Alice está definido en una cadena privada utilizando la tecnología |nombre_de_codigo|, mientras que el token de Bob solo está presente en la cadena pública de |nombre_de_codigo|.
Una solución no atómica podría ser:
Alice envía 10 tokens de Alice a Bob (cadena privada).
Bob recibe la transacción.
Bob envía 10 tokens de Bob a Alice (cadena pública).
Alice recibe la transacción.
Sin embargo, no se tienen tanta confianza el uno al otro. Como habrás notado, Bob podría quedarse con los tokens de Alice si decide no realizar el paso 3.
Esta guía te mostrará cómo definir una forma segura de intercambiar tokens entre diferentes participantes y redes.
Completa la sección de introducción.
Todos los participantes involucrados en el intercambio deben poseer al menos una cuenta en cada cadena de bloques:
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 = bitxor_sdk_1.Account.createFromPrivateKey(
'',
bitxor_sdk_1.NetworkType.MAIN_NET,
);
const alicePrivateChainAccount = bitxor_sdk_1.Account.createFromPrivateKey(
'',
bitxor_sdk_1.NetworkType.MIJIN,
);
const bobPublicChainAccount = bitxor_sdk_1.Account.createFromPrivateKey(
'',
bitxor_sdk_1.NetworkType.MAIN_NET,
);
const bobPrivateChainAccount = bitxor_sdk_1.Account.createFromPrivateKey(
'',
bitxor_sdk_1.NetworkType.MIJIN,
);
const privateChainTransactionHttp = new bitxor_sdk_1.TransactionHttp(
'http://localhost:3000',
);
const publicChainTransactionHttp = new bitxor_sdk_1.TransactionHttp(
'http://localhost:3000',
);
const publicChainGenerationHash = process.env.NETWORK_GENERATION_HASH;
const privateChainGenerationHash = process.env.NETWORK_GENERATION_HASH;
La cuenta de Alice en la cadena privada debe tener al menos 10 tokens de Alice.
La cuenta de Bob en la cadena pública debe tener al menos 10 tokens de Bob.
Ambas cuentas deben tener suficiente moneda de la red para pagar las tarifas de las transacciones.
1. Alice genera un conjunto aleatorio de bytes llamado “prueba” (proof). La prueba debe tener un tamaño entre 10 y 1000 bytes. Luego, aplica el algoritmo SHA3-256 a ella, obteniendo el “secreto” (secret).
Alice hace un hash de la prueba obtenida con uno de los algoritmos disponibles para generar el “secreto” (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 define la transacción TX1 de SecretLockTransaction:
Propiedad de TX1 |
Valor |
---|---|
Tipo |
SecretLockTransaction |
Token |
10 |
Destinatario |
Dirección de Bob (Cadena privada) |
Algoritmo |
SHA3-256 |
Duración |
96 horas |
Secreto |
SHA3-256(prueba) |
Red |
Cadena privada |
const tx1 = SecretLockTransaction.create(
Deadline.create(epochAdjustment),
new Token(new TokenId('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 = bitxor_sdk_1.SecretLockTransaction.create(
bitxor_sdk_1.Deadline.create(epochAdjustment),
new bitxor_sdk_1.Token(
new bitxor_sdk_1.TokenId('00D3378709746FC4'),
bitxor_sdk_1.UInt64.fromUint(10),
),
bitxor_sdk_1.UInt64.fromUint((96 * 3600) / 30), // assuming one block every 30 seconds
bitxor_sdk_1.LockHashAlgorithm.Op_Sha3_256,
secret,
bobPrivateChainAccount.address,
bitxor_sdk_1.NetworkType.MIJIN,
);
Una vez anunciada, esta transacción permanecerá bloqueada hasta que alguien descubra la prueba que coincide con el secreto. Si nadie lo desbloquea antes de que se alcance la duración establecida, los fondos bloqueados se devolverán a Alice.
Alice anuncia la TX1 en la red privada y comparte el secreto con Bob.
Note
Bob debe obtener el secreto de la cadena. Es responsabilidad de Bob verificar la corrección del secreto.
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 anuncia la siguiente SecretLockTransaction TX2 en la red pública
Propiedad de TX2 |
Valor |
---|---|
Tipo |
SecretLockTransaction |
Token |
10 |
Destinatario |
Dirección de Alice (Cadena pública) |
Algoritmo |
SHA3-256 |
Duración |
84 horas |
Secreto |
SHA3-256(prueba) |
Red |
Cadena pública |
const tx2 = SecretLockTransaction.create(
Deadline.create(epochAdjustment),
new Token(new TokenId('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 = bitxor_sdk_1.SecretLockTransaction.create(
bitxor_sdk_1.Deadline.create(epochAdjustment),
new bitxor_sdk_1.Token(
new bitxor_sdk_1.TokenId('10293DE77C684F71'),
bitxor_sdk_1.UInt64.fromUint(10),
),
bitxor_sdk_1.UInt64.fromUint((84 * 3600) / 30), // assuming one block every 30 seconds
bitxor_sdk_1.LockHashAlgorithm.Op_Sha3_256,
secret,
alicePublicChainAccount.address,
bitxor_sdk_1.NetworkType.MAIN_NET,
bitxor_sdk_1.UInt64.fromUint(2000000),
);
Note
La duración en la cual los fondos se pueden desbloquear debe ser un marco de tiempo más corto que el de TX1. Alice conoce el secreto, por lo que Bob debe asegurarse de tener tiempo suficiente después de que Alice revele el secreto.
Note
Para garantizar que TX1 no pueda ser revertida, Bob debe esperar hasta que TX1 reciba al menos maxRollBackBlocks
confirmaciones antes de anunciar TX2.
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 anuncia la SecretProofTransaction TX3 en la red pública. Esta transacción define el algoritmo de cifrado utilizado, la prueba original y el secreto:
Propiedad de TX3 |
Valor |
---|---|
Tipo |
SecretProofTransaction |
Destinatario |
Dirección de Alice (Cadena pública) |
Algoritmo |
SHA3-256 |
Secreto |
SHA3-256(prueba) |
Prueba |
prueba |
Red |
Cadena pública |
Note
Para garantizar que TX2 no pueda ser revertida, Alice debe esperar hasta que TX2 reciba al menos maxRollBackBlocks
confirmaciones antes de anunciar TX3.
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 = bitxor_sdk_1.SecretProofTransaction.create(
bitxor_sdk_1.Deadline.create(epochAdjustment),
bitxor_sdk_1.LockHashAlgorithm.Op_Sha3_256,
secret,
alicePublicChainAccount.address,
proof,
bitxor_sdk_1.NetworkType.MAIN_NET,
bitxor_sdk_1.UInt64.fromUint(2000000),
);
const tx3Signed = alicePublicChainAccount.sign(tx3, publicChainGenerationHash);
publicChainTransactionHttp.announce(tx3Signed).subscribe(
(x) => console.log(x),
(err) => console.error(err),
);
Una vez que se confirma TX3, se revela la prueba. Se desbloquea la transacción TX2, y Alice recibe los fondos bloqueados.
Bob selecciona la prueba y anuncia la SecretProofTransaction TX4 en la red privada, recibiendo los fondos bloqueados de la TX1.
Note
Para garantizar que TX3 no pueda ser revertida, Bob debe esperar hasta que TX3 reciba al menos maxRollBackBlocks
confirmaciones antes de anunciar TX4.
Propiedad de TX4 |
Valor |
---|---|
Tipo |
SecretProofTransaction |
Destinatario |
Dirección de Bob (Cadena privada) |
Algoritmo |
SHA3-256 |
Secreto |
SHA3-256(prueba) |
Prueba |
prueba |
Red |
Cadena privada |
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 = bitxor_sdk_1.SecretProofTransaction.create(
bitxor_sdk_1.Deadline.create(epochAdjustment),
bitxor_sdk_1.LockHashAlgorithm.Op_Sha3_256,
secret,
bobPrivateChainAccount.address,
proof,
bitxor_sdk_1.NetworkType.MIJIN,
);
const tx4Signed = bobPrivateChainAccount.sign(tx4, privateChainGenerationHash);
privateChainTransactionHttp.announce(tx4Signed).subscribe(
(x) => console.log(x),
(err) => console.error(err),
);
El proceso es atómico, pero debe completarse con mucho tiempo de anticipación antes de las fechas límite:
✅ Bob no quiere anunciar TX2: Alice recibirá sus fondos de vuelta después de 94 horas.
✅ Alice no anuncia TX3: Bob recibirá su reembolso después de 84 horas. Alice también desbloqueará sus fondos después de 94 horas.
⚠️Alice firma y anuncia TX3: Alice recibe los fondos de Bob. Bob tendrá suficiente tiempo para firmar TX4 porque la duración de TX1 es más larga que la de TX2.
⚠️Se produce una reversión y se reescribe el historial: Alice y Bob han esperado al menos maxRollBackBlocks
entre cada confirmación de transacción.