Changeset View
Changeset View
Standalone View
Standalone View
apps/alias-server/src/utils.js
// Copyright (c) 2023 The Bitcoin developers | // Copyright (c) 2023 The Bitcoin developers | ||||
// Distributed under the MIT software license, see the accompanying | // Distributed under the MIT software license, see the accompanying | ||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php. | // file COPYING or http://www.opensource.org/licenses/mit-license.php. | ||||
'use strict'; | 'use strict'; | ||||
const opReturn = require('../constants/op_return'); | |||||
module.exports = { | module.exports = { | ||||
getAliasFromHex: function (aliasHex) { | getAliasFromHex: function (aliasHex) { | ||||
return Buffer.from(aliasHex, 'hex').toString('utf8'); | return Buffer.from(aliasHex, 'hex').toString('utf8'); | ||||
}, | }, | ||||
getHexFromAlias: function (alias) { | getHexFromAlias: function (alias) { | ||||
return Buffer.from(alias, 'utf8').toString('hex'); | return Buffer.from(alias, 'utf8').toString('hex'); | ||||
}, | }, | ||||
Show All 17 Lines | removeUnconfirmedTxsFromTxHistory: function (txHistory) { | ||||
confirmedTxHistory.push(thisTx); | confirmedTxHistory.push(thisTx); | ||||
} | } | ||||
} | } | ||||
return confirmedTxHistory; | return confirmedTxHistory; | ||||
}, | }, | ||||
wait: async function (msecs) { | wait: async function (msecs) { | ||||
await new Promise(resolve => setTimeout(resolve, msecs)); | await new Promise(resolve => setTimeout(resolve, msecs)); | ||||
}, | }, | ||||
/** | |||||
* Get the next push from an OP_RETURN stack of a version 0 alias registration tx | |||||
* @param {object} stackObj {remainingHex: remaining stack as hex string} | |||||
* @param {string} | |||||
* @returns {string} the next push on the stack | |||||
* @modifies stackObj, removes the returned push | |||||
* @throws {Error} | |||||
*/ | |||||
getNextPush: function (stack) { | |||||
let remainingHex = stack.remainingHex; | |||||
const byteLength = 2; // one byte is 2 characters of a hex string | |||||
// Get the first byte on the stack | |||||
let firstByte = remainingHex.slice(0, 1 * byteLength); | |||||
// Remove firstByte from remainingHex | |||||
remainingHex = remainingHex.slice(1 * byteLength); | |||||
if (firstByte === opReturn.OP_RETURN) { | |||||
// If the first byte is '6a', reassign firstByte | |||||
// 6a just means this is the first push of an OP_RETURN | |||||
// Re-assign firstByte | |||||
firstByte = remainingHex.slice(0, 1 * byteLength); | |||||
// Remove 6a from remainingHex | |||||
remainingHex = remainingHex.slice(1 * byteLength); | |||||
} | |||||
// Initialize pushdata, the byteCount in hex of the push | |||||
let pushdata; | |||||
if (opReturn.oneByteStackAdds.includes(firstByte)) { | |||||
/** | |||||
* If this is a one-byte push, return the byte | |||||
* Modify the { stack } input in place | |||||
*/ | |||||
stack.remainingHex = remainingHex; | |||||
return firstByte; | |||||
} | |||||
if (opReturn.oneBytePushdatas.includes(firstByte)) { | |||||
// If the first byte on the stack is 0x01-0x4b, then this is pushdata | |||||
pushdata = firstByte; | |||||
} else if (firstByte === opReturn.OP_PUSHDATA1) { | |||||
// The next byte contains the number of bytes to be pushed onto the stack. | |||||
pushdata = remainingHex.slice(0, 1 * byteLength); | |||||
// Remove 1 byte pushdata from the stack | |||||
remainingHex = remainingHex.slice(1 * byteLength); | |||||
} else if (firstByte === opReturn.OP_PUSHDATA2) { | |||||
// The next two bytes contain the number of bytes to be pushed onto the stack in little endian order. | |||||
// Note: version 0 alias registration txs do not require more than one byte of pushdata | |||||
// So, if the other byte is not 0x00, throw an error | |||||
if (remainingHex.slice(1 * byteLength, 2 * byteLength) !== '00') { | |||||
throw new Error( | |||||
'Version 0 alias registrations cannot have pushdata > 255', | |||||
); | |||||
} | |||||
// pushdata is the first byte of the next 2 bytes, as little-endian | |||||
// i.e. 04 would be 0x04 0x00 | |||||
pushdata = remainingHex.slice(0, 1 * byteLength); | |||||
// Remove 2 bytes pushdata from the stack | |||||
remainingHex = remainingHex.slice(2 * byteLength); | |||||
} else if (firstByte === opReturn.OP_PUSHDATA4) { | |||||
// The next four bytes contain the number of bytes to be pushed onto the stack in little endian order. | |||||
// Note: version 0 alias registration txs do not require more than one byte of pushdata | |||||
// So, if the other three bytes are not 0x00, throw an error | |||||
if ( | |||||
remainingHex.slice(1 * byteLength, 4 * byteLength) !== '000000' | |||||
) { | |||||
throw new Error( | |||||
'Version 0 alias registrations cannot have pushdata > 255', | |||||
); | |||||
} | |||||
// pushdata is the first byte of the next 4 bytes, as little-endian | |||||
// i.e. 04 would be 0x04 0x00 | |||||
pushdata = remainingHex.slice(0, 2); | |||||
// Remove 4 bytes pushdata from the stack | |||||
remainingHex = remainingHex.slice(4 * byteLength); | |||||
} else { | |||||
throw new Error(`${firstByte} is invalid pushdata`); | |||||
} | |||||
// Now that you know pushdata in bytes, get the push | |||||
const pushdataBytes = parseInt(pushdata, 16); | |||||
// Modify the {stack} input in place | |||||
stack.remainingHex = remainingHex.slice(pushdataBytes * byteLength); | |||||
// Return the push | |||||
return remainingHex.slice(0, pushdataBytes * byteLength); | |||||
}, | |||||
}; | }; |