Inscription #70260870#70,260,870pngtransfer10.acd3#50,535,420brc-20transfer10.acd3#50,535,410brc-20transfer10.acd3#50,534,805brc-20transfer10.acd3#50,534,795brc-20transfer10.acd3#50,534,777brc-20transfer100.acd3#50,534,758brc-20transfer10.acd3#50,534,334brc-20transfer10.acd3#50,534,239brc-20transfer10.acd3#50,534,236brc-20transfer10.acd3#50,534,127brc-20mint1.𝑨#47,682,057brc-20deploy.𝑨#47,668,999brc-20deploy.𝛀#47,668,998brc-20const verifyTimestamps = (commitment, selection, reveal) => { return ( commitment.gameTimestamp < selection.selectionTimestamp && selection.selectionTimestamp < reveal.gameTimestamp ) }; const verifyGameNonce = (selection, reveal) => { return ( commitment.gameNonce === selection.gameNonce && selection.gameNonce === reveal.gameNonce ) } const verifyGameNonceSignature = (bitcore, verifyMessageSignatureRsv, ECPair, Buffer, commitment, selection) => { if (!commitment.gameNonce === selection.gameNonce) return const gameNonceHash = bitcore.crypto.Hash.sha256(Buffer.from(commitment.gameNonce)).toString('hex') const message = new bitcore.Message(gameNonceHash); var hash = message.magicHash(); // Using Bitcore for message hashing and verification try { var signature = bitcore.crypto.Signature.fromCompact( Buffer.from(selection.signedGameNonce, "base64") ); // recover the public key var ecdsa = new bitcore.crypto.ECDSA(); ecdsa.hashbuf = hash; ecdsa.sig = signature; const pubkeyInSig = ecdsa.toPublicKey(); const pubkeyInSigString = new bitcore.PublicKey( Object.assign({}, pubkeyInSig.toObject(), { compressed: true }) ).toString(); if (pubkeyInSigString != selection.userPublicKey) { return false; } return bitcore.crypto.ECDSA.verify(hash, signature, pubkeyInSig); } catch (e) { const publicKeyBuffer = Buffer.from(selection.userPublicKey, 'hex'); const keyPair = ECPair.fromPublicKey(publicKeyBuffer); const signatureBuffer = Buffer.from(selection.signedGameNonce, "base64"); if (signatureBuffer.length == 65) { const rawSignature = new Uint8Array(signatureBuffer).slice(1); const rawSignatureBuffer = Buffer.from(rawSignature); const isVerified = keyPair.verify(hash, rawSignatureBuffer); return isVerified } else if (signatureBuffer.length == 97) { const verified = verifyMessageSignatureRsv({ message: gameNonceHash, publicKey: selection.userPublicKey, signature: selection.signedGameNonce }); return verified } } } const verifyCommitmentIntegrity = (bitcore, Buffer, commitment, reveal) => { const reconstuctedCommitment = bitcore.crypto.Hash.sha256(Buffer.from(reveal.vrn + reveal.gameNonce + reveal.secretNonce)) return (reconstuctedCommitment.toString('hex') === commitment.commitment) } const verifyOutcomeHashValue = (bitcore, Buffer, selection, reveal) => { const choiceString = selection.choice ? "heads" : "tails" // True is heads, False is Tails const userData = bitcore.crypto.Hash.sha256(Buffer.from(choiceString + selection.gameNonce + selection.amount)) const outcomeHashBuffer = Buffer.from(reveal.vrn + userData.toString('hex')); const outcomeHash = bitcore.crypto.Hash.sha256(outcomeHashBuffer) return Buffer.from(reveal.outcomeHash).toString('hex') === outcomeHash.toString('hex') } const verifyGameOutcome = (reveal) => { const outcomeHash = Buffer.from(reveal.outcomeHash).toString('hex') const outcome = parseInt(outcomeHash[outcomeHash.length - 1], 16) % 2 === 0 ? "heads" : "tails" return outcome === reveal.outcomeString } const checks = { 'Timestamp Verification': verifyTimestamps(commitment, selection, reveal), 'Game Nonce Verification': verifyGameNonce(selection, reveal), 'Game Nonce Signature Verification': verifyGameNonceSignature(bitcore, verifyMessageSignatureRsv, ECPair, Buffer, commitment, selection), 'Commitment Integrity Verification': verifyCommitmentIntegrity(bitcore, Buffer, commitment, reveal), 'Outcome Hash Verification': verifyOutcomeHashValue(bitcore, Buffer, selection, reveal), 'Game Outcome Verification': verifyGameOutcome(reveal) }; let allChecksPass = true; for (const [checkName, result] of Object.entries(checks)) { if (result) { console.log(`✅ - ${checkName}`); } else { console.log(`❌ - ${checkName}`); allChecksPass = false; } } if (allChecksPass) { console.log(`Congratulations, you have carried out a direct stateless verification of a trustlessly random coin flip, which you ${reveal.didWin ? '✨won✨' : 'lost'}`); } else { console.log(`This is mathematically impossible, contact a member of the team for help on how to verify.`); } return allChecksPass#36,822,068textconst verifyTimestamps = (commitment, selection, reveal) => { return ( commitment.gameTimestamp < selection.selectionTimestamp && selection.selectionTimestamp < reveal.gameTimestamp ) }; const verifyGameNonce = (selection, reveal) => { return ( commitment.gameNonce === selection.gameNonce && selection.gameNonce === reveal.gameNonce ) } const verifyGameNonceSignature = (bitcore, verifyMessageSignatureRsv, ECPair, Buffer, commitment, selection) => { if (!commitment.gameNonce === selection.gameNonce) return const gameNonceHash = bitcore.crypto.Hash.sha256(Buffer.from(commitment.gameNonce)).toString('hex') const message = new bitcore.Message(gameNonceHash); var hash = message.magicHash(); // Using Bitcore for message hashing and verification try { var signature = bitcore.crypto.Signature.fromCompact( Buffer.from(selection.signedGameNonce, "base64") ); // recover the public key var ecdsa = new bitcore.crypto.ECDSA(); ecdsa.hashbuf = hash; ecdsa.sig = signature; const pubkeyInSig = ecdsa.toPublicKey(); const pubkeyInSigString = new bitcore.PublicKey( Object.assign({}, pubkeyInSig.toObject(), { compressed: true }) ).toString(); if (pubkeyInSigString != selection.userPublicKey) { return false; } return bitcore.crypto.ECDSA.verify(hash, signature, pubkeyInSig); } catch (e) { const publicKeyBuffer = Buffer.from(selection.userPublicKey, 'hex'); const keyPair = ECPair.fromPublicKey(publicKeyBuffer); const signatureBuffer = Buffer.from(selection.signedGameNonce, "base64"); if (signatureBuffer.length == 65) { const rawSignature = new Uint8Array(signatureBuffer).slice(1); const rawSignatureBuffer = Buffer.from(rawSignature); const isVerified = keyPair.verify(hash, rawSignatureBuffer); return isVerified } else if (signatureBuffer.length == 97) { const verified = verifyMessageSignatureRsv({ message: gameNonceHash, publicKey: selection.userPublicKey, signature: selection.signedGameNonce }); return verified } } } const verifyCommitmentIntegrity = (bitcore, Buffer, commitment, reveal) => { const reconstuctedCommitment = bitcore.crypto.Hash.sha256(Buffer.from(reveal.vrn + reveal.gameNonce + reveal.secretNonce)) return (reconstuctedCommitment.toString('hex') === commitment.commitment) } const verifyOutcomeHashValue = (bitcore, Buffer, selection, reveal) => { const choiceString = selection.choice ? "heads" : "tails" // True is heads, False is Tails const userData = bitcore.crypto.Hash.sha256(Buffer.from(choiceString + selection.gameNonce + selection.amount)) const outcomeHashBuffer = Buffer.from(reveal.vrn + userData.toString('hex')); const outcomeHash = bitcore.crypto.Hash.sha256(outcomeHashBuffer) return Buffer.from(reveal.outcomeHash).toString('hex') === outcomeHash.toString('hex') } const verifyGameOutcome = (reveal) => { const outcome = parseInt(reveal.outcomeHash[reveal.outcomeHash.length - 1], 16) % 2 === 0 ? "heads" : "tails" return outcome === reveal.outcomeString } const checks = { 'Timestamp Verification': verifyTimestamps(commitment, selection, reveal), 'Game Nonce Verification': verifyGameNonce(selection, reveal), 'Game Nonce Signature Verification': verifyGameNonceSignature(bitcore, verifyMessageSignatureRsv, ECPair, Buffer, commitment, selection), 'Commitment Integrity Verification': verifyCommitmentIntegrity(bitcore, Buffer, commitment, reveal), 'Outcome Hash Verification': verifyOutcomeHashValue(bitcore, Buffer, selection, reveal), 'Game Outcome Verification': verifyGameOutcome(reveal) }; let allChecksPass = true; for (const [checkName, result] of Object.entries(checks)) { if (result) { console.log(`✅ - ${checkName}`); } else { console.log(`❌ - ${checkName}`); allChecksPass = false; } } if (allChecksPass) { console.log(`Congratulations, you have carried out a direct stateless verification of a trustlessly random coin flip, which you ${reveal.didWin ? '✨won✨' : 'lost'}`); } else { console.log(`This is mathematically impossible, contact a member of the team for help on how to verify.`); } return allChecksPass#36,820,933textconst verifyTimestamps = (commitment, selection, reveal) => { return ( commitment.gameTimestamp < selection.selectionTimestamp && selection.selectionTimestamp < reveal.gameTimestamp ) }; const verifyGameNonce = (selection, reveal) => { return ( commitment.gameNonce === selection.gameNonce && selection.gameNonce === reveal.gameNonce ) } const verifyGameNonceSignature = (bitcore, verifyMessageSignatureRsv, ECPair, Buffer, commitment, selection) => { if (!commitment.gameNonce === selection.gameNonce) return const gameNonceHash = bitcore.crypto.Hash.sha256(Buffer.from(commitment.gameNonce)).toString('hex') const message = new bitcore.Message(gameNonceHash); var hash = message.magicHash(); // Using Bitcore for message hashing and verification try { var signature = bitcore.crypto.Signature.fromCompact( Buffer.from(selection.signedGameNonce, "base64") ); // recover the public key var ecdsa = new bitcore.crypto.ECDSA(); ecdsa.hashbuf = hash; ecdsa.sig = signature; const pubkeyInSig = ecdsa.toPublicKey(); const pubkeyInSigString = new bitcore.PublicKey( Object.assign({}, pubkeyInSig.toObject(), { compressed: true }) ).toString(); if (pubkeyInSigString != selection.userPublicKey) { return false; } return bitcore.crypto.ECDSA.verify(hash, signature, pubkeyInSig); } catch (e) { const publicKeyBuffer = Buffer.from(selection.userPublicKey, 'hex'); const keyPair = ECPair.fromPublicKey(publicKeyBuffer); const signatureBuffer = Buffer.from(selection.signedGameNonce, "base64"); if (signatureBuffer.length == 65) { const rawSignature = new Uint8Array(signatureBuffer).slice(1); const rawSignatureBuffer = Buffer.from(rawSignature); const isVerified = keyPair.verify(hash, rawSignatureBuffer); return isVerified } else if (signatureBuffer.length == 97) { const verified = verifyMessageSignatureRsv({ message: gameNonceHash, publicKey: selection.userPublicKey, signature: selection.signedGameNonce }); return verified } } } const verifyCommitmentIntegrity = (bitcore, Buffer, commitment, reveal) => { const reconstuctedCommitment = bitcore.crypto.Hash.sha256(Buffer.from(reveal.vrn + reveal.gameNonce + reveal.secretNonce)) return (reconstuctedCommitment.toString('hex') === commitment.commitment) } const verifyOutcomeHashValue = (bitcore, Buffer, selection, reveal) => { console.log('===== Debugging verifyOutcomeHashValue ====='); console.log('Selection:', JSON.stringify(selection)); console.log('Reveal:', JSON.stringify(reveal)); const choiceString = selection.choice ? "heads" : "tails"; console.log('Choice String:', choiceString); const userDataBuffer = Buffer.from(choiceString + selection.gameNonce + selection.amount); console.log('User Data Buffer:', userDataBuffer.toString('hex')); const userData = bitcore.crypto.Hash.sha256(userDataBuffer); console.log('User Data:', userData.toString('hex')); const outcomeHashBuffer = Buffer.from(reveal.vrn + userData); console.log('Outcome Hash Buffer:', outcomeHashBuffer.toString('hex')); const outcomeHash = bitcore.crypto.Hash.sha256(outcomeHashBuffer); console.log('Outcome Hash:', outcomeHash.toString('hex')); const revealOutcomeHashBuffer = Buffer.from(reveal.outcomeHash); console.log('Reveal Outcome Hash Buffer:', revealOutcomeHashBuffer.toString('hex')); const isEqual = revealOutcomeHashBuffer.toString('hex') === outcomeHash.toString('hex'); console.log('Is Equal:', isEqual); return isEqual; }; const verifyGameOutcome = (reveal) => { const outcome = parseInt(reveal.outcomeHash[reveal.outcomeHash.length - 1], 16) % 2 === 0 ? "heads" : "tails" return outcome === reveal.outcomeString } const checks = { 'Timestamp Verification': verifyTimestamps(commitment, selection, reveal), 'Game Nonce Verification': verifyGameNonce(selection, reveal), 'Game Nonce Signature Verification': verifyGameNonceSignature(bitcore, verifyMessageSignatureRsv, ECPair, Buffer, commitment, selection), 'Commitment Integrity Verification': verifyCommitmentIntegrity(bitcore, Buffer, commitment, reveal), 'Outcome Hash Verification': verifyOutcomeHashValue(bitcore, Buffer, selection, reveal), 'Game Outcome Verification': verifyGameOutcome(reveal) }; let allChecksPass = true; for (const [checkName, result] of Object.entries(checks)) { console.log(checkName) if (result) { console.log(`✅ - ${checkName}`); } else { console.log(`❌ - ${checkName}`); allChecksPass = false; } } if (allChecksPass) { console.log(`Congratulations, you have carried out a direct stateless verification of a trustlessly random coin flip, which you ${reveal.didWin ? '✨won✨' : 'lost'}`); } else { console.log(`This is mathematically impossible, contact a member of the team for help on how to verify.`); } return allChecksPass#36,795,192textconst verifyTimestamps = (commitment, selection, reveal) => { return ( commitment.gameTimestamp < selection.selectionTimestamp && selection.selectionTimestamp < reveal.gameTimestamp ) }; const verifyGameNonce = (selection, reveal) => { return ( commitment.gameNonce === selection.gameNonce && selection.gameNonce === reveal.gameNonce ) } const verifyGameNonceSignature = (bitcore, verifyMessageSignatureRsv, ECPair, Buffer, commitment, selection) => { if (!commitment.gameNonce === selection.gameNonce) return const gameNonceHash = bitcore.crypto.Hash.sha256(Buffer.from(commitment.gameNonce)).toString('hex') const message = new bitcore.Message(gameNonceHash); var hash = message.magicHash(); // Using Bitcore for message hashing and verification try { var signature = bitcore.crypto.Signature.fromCompact( Buffer.from(selection.signedGameNonce, "base64") ); // recover the public key var ecdsa = new bitcore.crypto.ECDSA(); ecdsa.hashbuf = hash; ecdsa.sig = signature; const pubkeyInSig = ecdsa.toPublicKey(); const pubkeyInSigString = new bitcore.PublicKey( Object.assign({}, pubkeyInSig.toObject(), { compressed: true }) ).toString(); if (pubkeyInSigString != selection.userPublicKey) { return false; } return bitcore.crypto.ECDSA.verify(hash, signature, pubkeyInSig); } catch (e) { const publicKeyBuffer = Buffer.from(selection.userPublicKey, 'hex'); const keyPair = ECPair.fromPublicKey(publicKeyBuffer); const signatureBuffer = Buffer.from(selection.signedGameNonce, "base64"); if (signatureBuffer.length == 65) { const rawSignature = new Uint8Array(signatureBuffer).slice(1); const rawSignatureBuffer = Buffer.from(rawSignature); const isVerified = keyPair.verify(hash, rawSignatureBuffer); return isVerified } else if (signatureBuffer.length == 97) { const verified = verifyMessageSignatureRsv({ message: gameNonceHash, publicKey: selection.userPublicKey, signature: selection.signedGameNonce }); return verified } } } const verifyCommitmentIntegrity = (bitcore, Buffer, commitment, reveal) => { const reconstuctedCommitment = bitcore.crypto.Hash.sha256(Buffer.from(reveal.vrn + reveal.gameNonce + reveal.secretNonce)) return (reconstuctedCommitment.toString('hex') === commitment.commitment) } const verifyOutcomeHashValue = (bitcore, Buffer, selection, reveal) => { const choiceString = selection.choice ? "heads" : "tails" // True is heads, False is Tails const userData = bitcore.crypto.Hash.sha256(Buffer.from(choiceString + selection.gameNonce + selection.amount)) const outcomeHash = bitcore.crypto.Hash.sha256(Buffer.from(reveal.vrn + userData)) return Buffer.from(reveal.outcomeHash).toString('hex') === outcomeHash.toString('hex') } const verifyGameOutcome = (reveal) => { const outcome = parseInt(reveal.outcomeHash[reveal.outcomeHash.length - 1], 16) % 2 === 0 ? "heads" : "tails" return outcome === reveal.outcomeString } const checks = { 'Timestamp Verification': verifyTimestamps(commitment, selection, reveal), 'Game Nonce Verification': verifyGameNonce(selection, reveal), 'Game Nonce Signature Verification': verifyGameNonceSignature(bitcore, verifyMessageSignatureRsv, ECPair, Buffer, commitment, selection), 'Commitment Integrity Verification': verifyCommitmentIntegrity(bitcore, Buffer, commitment, reveal), 'Outcome Hash Verification': verifyOutcomeHashValue(bitcore, Buffer, selection, reveal), 'Game Outcome Verification': verifyGameOutcome(reveal) }; let allChecksPass = true; for (const [checkName, result] of Object.entries(checks)) { console.log(checkName) if (result) { console.log(`✅ - ${checkName}`); } else { console.log(`❌ - ${checkName}`); allChecksPass = false; } } if (allChecksPass) { console.log(`Congratulations, you have carried out a direct stateless verification of a trustlessly random coin flip, which you ${reveal.didWin ? '✨won✨' : 'lost'}`); } else { console.log(`This is mathematically impossible, contact a member of the team for help on how to verify.`); } return allChecksPass#36,772,779textconst verifyTimestamps = (commitment, selection, reveal) => { return ( commitment.gameTimestamp < selection.selectionTimestamp && selection.selectionTimestamp < reveal.gameTimestamp ) }; const verifyGameNonce = (selection, reveal) => { return ( commitment.gameNonce === selection.gameNonce && selection.gameNonce === reveal.gameNonce ) } const verifyGameNonceSignature = (bitcore, verifyMessageSignatureRsv, ECPair, commitment, selection, reveal) => { if (!commitment.gameNonce === selection.gameNonce) return const gameNonceHash = bitcore.crypto.Hash.sha256(Buffer.from(commitment.gameNonce)).toString('hex') const message = new bitcore.Message(gameNonceHash); var hash = message.magicHash(); // Using Bitcore for message hashing and verification try { var signature = bitcore.crypto.Signature.fromCompact( Buffer.from(selection.signedGameNonce, "base64") ); // recover the public key var ecdsa = new bitcore.crypto.ECDSA(); ecdsa.hashbuf = hash; ecdsa.sig = signature; const pubkeyInSig = ecdsa.toPublicKey(); const pubkeyInSigString = new bitcore.PublicKey( Object.assign({}, pubkeyInSig.toObject(), { compressed: true }) ).toString(); if (pubkeyInSigString != selection.userPublicKey) { return false; } return bitcore.crypto.ECDSA.verify(hash, signature, pubkeyInSig); } catch (e) { const publicKeyBuffer = Buffer.from(selection.userPublicKey, 'hex'); const keyPair = ECPair.fromPublicKey(publicKeyBuffer); const signatureBuffer = Buffer.from(selection.signedGameNonce, "base64"); if (signatureBuffer.length == 65) { const rawSignature = new Uint8Array(signatureBuffer).slice(1); const rawSignatureBuffer = Buffer.from(rawSignature); const isVerified = keyPair.verify(hash, rawSignatureBuffer); return isVerified } else if (signatureBuffer.length == 97) { const verified = verifyMessageSignatureRsv({ message: gameNonceHash, publicKey: selection.userPublicKey, signature: selection.signedGameNonce }); return verified } } } const verifyCommitmentIntegrity = (bitcore, commitment, reveal) => { const reconstuctedCommitment = bitcore.crypto.Hash.sha256(Buffer.from(reveal.vrn + reveal.gameNonce + reveal.secretNonce)) return (reconstuctedCommitment.toString('hex') === commitment.commitment) } const verifyOutcomeHashValue = (bitcore, selection, reveal) => { const choiceString = selection.choice ? "heads" : "tails" // True is heads, False is Tails const userData = bitcore.crypto.Hash.sha256(Buffer.from(choiceString + selection.gameNonce + selection.amount)) const outcomeHash = bitcore.crypto.Hash.sha256(Buffer.from(reveal.vrn + userData)) return Buffer.from(reveal.outcomeHash).toString('hex') === outcomeHash.toString('hex') } const verifyGameOutcome = (reveal) => { const outcome = parseInt(reveal.outcomeHash[reveal.outcomeHash.length - 1], 16) % 2 === 0 ? "heads" : "tails" return outcome === reveal.outcomeString } const checks = { 'Timestamp Verification': verifyTimestamps(commitment, selection, reveal), 'Game Nonce Verification': verifyGameNonce(selection, reveal), 'Game Nonce Signature Verification': verifyGameNonceSignature(bitcore, verifyMessageSignatureRsv, ECPair, commitment, selection), 'Commitment Integrity Verification': verifyCommitmentIntegrity(bitcore, commitment, reveal), 'Outcome Hash Verification': verifyOutcomeHashValue(bitcore,selection, reveal), 'Game Outcome Verification': verifyGameOutcome(reveal) }; let allChecksPass = true; for (const [checkName, result] of Object.entries(checks)) { console.log(checkName) if (result) { console.log(`✅ - ${checkName}`); } else { console.log(`❌ - ${checkName}`); allChecksPass = false; } } if (allChecksPass) { console.log(`Congratulations, you have carried out a direct stateless verification of a trustlessly random coin flip, which you ${reveal.didWin ? '✨won✨' : 'lost'}`); } else { console.log(`This is mathematically impossible, contact a member of the team for help on how to verify.`); } return allChecksPass#36,749,621textconst verifyTimestamps = (commitment, selection, reveal) => { return ( commitment.gameTimestamp < selection.selectionTimestamp && selection.selectionTimestamp < reveal.gameTimestamp ) }; const verifyGameNonce = (selection, reveal) => { return ( commitment.gameNonce === selection.gameNonce && selection.gameNonce === reveal.gameNonce ) } const verifyGameNonceSignature = (bitcore, verifyMessageSignatureRsv, ECPair, commitment, selection, reveal) => { if (!commitment.gameNonce === selection.gameNonce) return const gameNonceHash = bitcore.crypto.Hash.sha256(Buffer.from(commitment.gameNonce)).toString('hex') const message = new bitcore.Message(gameNonceHash); var hash = message.magicHash(); // Using Bitcore for message hashing and verification try { var signature = bitcore.crypto.Signature.fromCompact( Buffer.from(selection.signedGameNonce, "base64") ); // recover the public key var ecdsa = new bitcore.crypto.ECDSA(); ecdsa.hashbuf = hash; ecdsa.sig = signature; const pubkeyInSig = ecdsa.toPublicKey(); const pubkeyInSigString = new bitcore.PublicKey( Object.assign({}, pubkeyInSig.toObject(), { compressed: true }) ).toString(); if (pubkeyInSigString != selection.userPublicKey) { return false; } return bitcore.crypto.ECDSA.verify(hash, signature, pubkeyInSig); } catch (e) { const publicKeyBuffer = Buffer.from(selection.userPublicKey, 'hex'); const keyPair = ECPair.fromPublicKey(publicKeyBuffer); const signatureBuffer = Buffer.from(selection.signedGameNonce, "base64"); if (signatureBuffer.length == 65) { const rawSignature = new Uint8Array(signatureBuffer).slice(1); const rawSignatureBuffer = Buffer.from(rawSignature); const isVerified = keyPair.verify(hash, rawSignatureBuffer); return isVerified } else if (signatureBuffer.length == 97) { const verified = verifyMessageSignatureRsv({ message: gameNonceHash, publicKey: selection.userPublicKey, signature: selection.signedGameNonce }); return verified } } } const verifyCommitmentIntegrity = (bitcore, commitment, reveal) => { const reconstuctedCommitment = bitcore.crypto.Hash.sha256(Buffer.from(reveal.vrn + reveal.gameNonce + reveal.secretNonce)) return (reconstuctedCommitment.toString('hex') === commitment.commitment) } const verifyOutcomeHashValue = (bitcore, selection, reveal) => { const choiceString = selection.choice ? "heads" : "tails" // True is heads, False is Tails const userData = bitcore.crypto.Hash.sha256(Buffer.from(choiceString + selection.gameNonce + selection.amount)) const outcomeHash = bitcore.crypto.Hash.sha256(Buffer.from(reveal.vrn + userData)) return Buffer.from(reveal.outcomeHash).toString('hex') === outcomeHash.toString('hex') } const verifyGameOutcome = (reveal) => { const outcome = parseInt(reveal.outcomeHash[reveal.outcomeHash.length - 1], 16) % 2 === 0 ? "heads" : "tails" return outcome === reveal.outcomeString } const checks = { 'Timestamp Verification': verifyTimestamps(commitment, selection, reveal), 'Game Nonce Verification': verifyGameNonce(selection, reveal), 'Game Nonce Signature Verification': verifyGameNonceSignature(bitcore, verifyMessageSignatureRsv, ECPair, commitment, selection), 'Commitment Integrity Verification': verifyCommitmentIntegrity(bitcore, commitment, reveal), 'Outcome Hash Verification': verifyOutcomeHashValue(bitcore,selection, reveal), 'Game Outcome Verification': verifyGameOutcome(reveal) }; let allChecksPass = true; for (const [checkName, result] of Object.entries(checks)) { console.log(checkName) if (result) { console.log(`✅ - ${checkName}`); } else { console.log(`❌ - ${checkName}`); allChecksPass = false; } } if (allChecksPass) { console.log(`Congratulations, you have carried out a direct stateless verification of a trustlessly random coin flip, which you ${reveal.didWin ? '✨won✨' : 'lost'}`); } else { console.log(`This is mathematically impossible, contact a member of the team for help on how to verify.`); } return allChecksPass#36,746,688textconst verifyTimestamps = (commitment, selection, reveal) => { return ( commitment.gameTimestamp < selection.selectionTimestamp && selection.selectionTimestamp < reveal.gameTimestamp ) }; const verifyGameNonce = (selection, reveal) => { return ( commitment.gameNonce === selection.gameNonce && selection.gameNonce === reveal.gameNonce ) } const verifyGameNonceSignature = (bitcore, verifyMessageSignatureRsv, ECPair, commitment, selection, reveal) => { if (!commitment.gameNonce === selection.gameNonce) return const gameNonceHash = bitcore.crypto.Hash.sha256(Buffer.from(commitment.gameNonce)).toString('hex') const message = new bitcore.Message(gameNonceHash); var hash = message.magicHash(); // Using Bitcore for message hashing and verification try { var signature = bitcore.crypto.Signature.fromCompact( Buffer.from(selection.signedGameNonce, "base64") ); // recover the public key var ecdsa = new bitcore.crypto.ECDSA(); ecdsa.hashbuf = hash; ecdsa.sig = signature; const pubkeyInSig = ecdsa.toPublicKey(); const pubkeyInSigString = new bitcore.PublicKey( Object.assign({}, pubkeyInSig.toObject(), { compressed: true }) ).toString(); if (pubkeyInSigString != selection.userPublicKey) { return false; } return bitcore.crypto.ECDSA.verify(hash, signature, pubkeyInSig); } catch (e) { const publicKeyBuffer = Buffer.from(selection.userPublicKey, 'hex'); const keyPair = ECPair.fromPublicKey(publicKeyBuffer); const signatureBuffer = Buffer.from(selection.signedGameNonce, "base64"); if (signatureBuffer.length == 65) { const rawSignature = new Uint8Array(signatureBuffer).slice(1); const rawSignatureBuffer = Buffer.from(rawSignature); const isVerified = keyPair.verify(hash, rawSignatureBuffer); return isVerified } else if (signatureBuffer.length == 97) { const verified = verifyMessageSignatureRsv({ message: gameNonceHash, publicKey: selection.userPublicKey, signature: selection.signedGameNonce }); return verified } } } const verifyCommitmentIntegrity = (bitcore, commitment, reveal) => { const reconstuctedCommitment = bitcore.crypto.Hash.sha256(Buffer.from(reveal.vrn + reveal.gameNonce + reveal.secretNonce)) return (reconstuctedCommitment.toString('hex') === commitment.commitment) } const verifyOutcomeHashValue = (bitcore, selection, reveal) => { const choiceString = selection.choice ? "heads" : "tails" // True is heads, False is Tails const userData = bitcore.crypto.Hash.sha256(Buffer.from(choiceString + selection.gameNonce + selection.amount)) const outcomeHash = bitcore.crypto.Hash.sha256(Buffer.from(reveal.vrn + userData)) return Buffer.from(reveal.outcomeHash).toString('hex')=== outcomeHash.toString('hex') } const verifyGameOutcome = (reveal) => { const outcome = parseInt(reveal.outcomeHash[reveal.outcomeHash.length - 1], 16) % 2 === 0 ? "heads" : "tails" return outcome === reveal.outcomeString } const checks = { 'Timestamp Verification': verifyTimestamps(commitment, selection, reveal), 'Game Nonce Verification': verifyGameNonce(bitcore, verifyMessageSignatureRsv, ECPair, commitment, selection, reveal), 'Game Nonce Signature Verification': verifyGameNonceSignature(bitcore,verifyMessageSignatureRsv, ECPair, commitment, selection), 'Commitment Integrity Verification': verifyCommitmentIntegrity(bitcore,verifyMessageSignatureRsv, ECPair, commitment, reveal), 'Outcome Hash Verification': verifyOutcomeHashValue(bitcore,verifyMessageSignatureRsv, ECPair, selection, reveal), 'Game Outcome Verification': verifyGameOutcome(bitcore,verifyMessageSignatureRsv, ECPair, reveal) }; let allChecksPass = true; for (const [checkName, result] of Object.entries(checks)) { console.log(checkName) if (result) { console.log(`✅ - ${checkName}`); } else { console.log(`❌ - ${checkName}`); allChecksPass = false; } } if (allChecksPass) { console.log(`Congratulations, you have carried out a direct stateless verification of a trustlessly random coin flip, which you ${reveal.didWin ? '✨won✨' : 'lost'}`); } else { console.log(`This is mathematically impossible, contact a member of the team for help on how to verify.`); } return allChecksPass#36,743,657textconst bitcore = require("bitcore-lib"); const { verifyMessageSignatureRsv } = require('@stacks/encryption'); const { ECPairFactory } = require('ecpair'); const tinysecp = require('tiny-secp256k1'); const ECPair = ECPairFactory(tinysecp); const verifyData = (commitment, selection, reveal) => { const checks = { 'Timestamp Verification': verifyTimestamps(commitment, selection, reveal), 'Game Nonce Verification': verifyGameNonce(commitment, selection, reveal), 'Game Nonce Signature Verification': verifyGameNonceSignature(commitment, selection), 'Commitment Integrity Verification': verifyCommitmentIntegrity(commitment, reveal), 'Outcome Hash Verification': verifyOutcomeHashValue(selection, reveal), 'Game Outcome Verification': verifyGameOutcome(reveal) }; let allChecksPass = true; for (const [checkName, result] of Object.entries(checks)) { if (result) { console.log(`✅ - ${checkName}`); } else { console.log(`❌ - ${checkName}`); allChecksPass = false; } } if (allChecksPass) { console.log(`Congratulations, you have carried out a direct stateless verification of a trustlessly random coin flip, which you ${reveal.didWin ? '✨won✨' : 'lost'}`); } else { console.log(`This is mathematically impossible, contact a member of the team for help on how to verify.`); } }; const verifyTimestamps = (commitment, selection, reveal) => { return ( commitment.gameTimestamp < selection.selectionTimestamp && selection.selectionTimestamp < reveal.gameTimestamp ) }; const verifyGameNonce = (commitment, selection, reveal) => { return ( commitment.gameNonce === selection.gameNonce && selection.gameNonce === reveal.gameNonce ) } const verifyGameNonceSignature = (commitment, selection) => { if (!commitment.gameNonce === selection.gameNonce) return const gameNonceHash = bitcore.crypto.Hash.sha256(Buffer.from(commitment.gameNonce)).toString('hex') const message = new bitcore.Message(gameNonceHash); var hash = message.magicHash(); // Using Bitcore for message hashing and verification try { var signature = bitcore.crypto.Signature.fromCompact( Buffer.from(selection.signedGameNonce, "base64") ); // recover the public key var ecdsa = new bitcore.crypto.ECDSA(); ecdsa.hashbuf = hash; ecdsa.sig = signature; const pubkeyInSig = ecdsa.toPublicKey(); const pubkeyInSigString = new bitcore.PublicKey( Object.assign({}, pubkeyInSig.toObject(), { compressed: true }) ).toString(); if (pubkeyInSigString != selection.userPublicKey) { return false; } return bitcore.crypto.ECDSA.verify(hash, signature, pubkeyInSig); } catch (e) { const publicKeyBuffer = Buffer.from(selection.userPublicKey, 'hex'); const keyPair = ECPair.fromPublicKey(publicKeyBuffer); const signatureBuffer = Buffer.from(selection.signedGameNonce, "base64"); if (signatureBuffer.length == 65) { const rawSignature = new Uint8Array(signatureBuffer).slice(1); const rawSignatureBuffer = Buffer.from(rawSignature); const isVerified = keyPair.verify(hash, rawSignatureBuffer); return isVerified } else if (signatureBuffer.length == 97) { const verified = verifyMessageSignatureRsv({ message: gameNonceHash, publicKey: selection.userPublicKey, signature: selection.signedGameNonce }); return verified } } } const verifyCommitmentIntegrity = (commitment, reveal) => { const reconstuctedCommitment = bitcore.crypto.Hash.sha256(Buffer.from(reveal.vrn + reveal.gameNonce + reveal.secretNonce)) return (reconstuctedCommitment.toString('hex') === commitment.commitment) } const verifyOutcomeHashValue = (selection, reveal) => { const userData = bitcore.crypto.Hash.sha256(Buffer.from(selection.choice + selection.gameNonce + selection.amount)) const outcomeHash = bitcore.crypto.Hash.sha256(Buffer.from(reveal.vrn + userData)) return outcomeHash.toString('hex') === reveal.outcomeHash } const verifyGameOutcome = (reveal) => { const outcome = parseInt(reveal.outcomeHash[reveal.outcomeHash.length - 1], 16) % 2 === 0 ? "tails" : "heads" return outcome === reveal.outcomeString } (async (commitment, selection, reveal) => { await verifyData(commitment, selection, reveal); })();#36,383,197textmint6,900,000.λrc#27,272,386brc-20mint6,900,000.acd3#27,269,383brc-20deploy.λrc#27,268,512brc-20mint6,900,000.λrc#27,268,511brc-20deploy.acd3#27,268,510brc-20mint6,900,000.acd3#27,268,509brc-20380152.bitmap#13,452,171text