Changeset View
Changeset View
Standalone View
Standalone View
apps/alias-server/test/utilsTests.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 assert = require('assert'); | const assert = require('assert'); | ||||
const { | const { | ||||
getAliasFromHex, | getAliasFromHex, | ||||
getHexFromAlias, | getHexFromAlias, | ||||
getAliasBytecount, | getAliasBytecount, | ||||
isValidAliasString, | isValidAliasString, | ||||
removeUnconfirmedTxsFromTxHistory, | removeUnconfirmedTxsFromTxHistory, | ||||
getNextPush, | |||||
} = require('../src/utils'); | } = require('../src/utils'); | ||||
const unconfirmedAliasTxs = require('./mocks/unconfirmedAliasTxs'); | |||||
const { | const { | ||||
aliasHexConversions, | aliasHexConversions, | ||||
validAliasStrings, | validAliasStrings, | ||||
invalidAliasStrings, | invalidAliasStrings, | ||||
} = require('./mocks/utilsMocks'); | } = require('./mocks/utilsMocks'); | ||||
const { testAddressAliases } = require('./mocks/aliasMocks'); | const { generated } = require('./mocks/aliasMocks'); | ||||
describe('alias-server utils.js', function () { | describe('alias-server utils.js', function () { | ||||
it('Hexadecimal to utf8 encoding functions work forward and backward. Byte counts match hexadecimal bytes.', function () { | it('Hexadecimal to utf8 encoding functions work forward and backward. Byte counts match hexadecimal bytes.', function () { | ||||
for (let i = 0; i < aliasHexConversions.length; i += 1) { | for (let i = 0; i < aliasHexConversions.length; i += 1) { | ||||
const { alias, aliasHex, aliasByteCount } = aliasHexConversions[i]; | const { alias, aliasHex, aliasByteCount } = aliasHexConversions[i]; | ||||
assert.deepEqual(getHexFromAlias(alias), aliasHex); | assert.deepEqual(getHexFromAlias(alias), aliasHex); | ||||
assert.deepEqual(getAliasFromHex(aliasHex), alias); | assert.deepEqual(getAliasFromHex(aliasHex), alias); | ||||
assert.deepEqual(getAliasBytecount(alias), aliasByteCount); | assert.deepEqual(getAliasBytecount(alias), aliasByteCount); | ||||
} | } | ||||
}); | }); | ||||
it('Recognizes lower case alphanumeric strings as valid alias strings', function () { | it('Recognizes lower case alphanumeric strings as valid alias strings', function () { | ||||
for (let i = 0; i < validAliasStrings.length; i += 1) { | for (let i = 0; i < validAliasStrings.length; i += 1) { | ||||
const validAliasString = validAliasStrings[i]; | const validAliasString = validAliasStrings[i]; | ||||
assert.deepEqual(isValidAliasString(validAliasString), true); | assert.deepEqual(isValidAliasString(validAliasString), true); | ||||
} | } | ||||
}); | }); | ||||
it('Recognizes strings with characters other than lower case a-z or numbers 0-9 as invalid alias strings', function () { | it('Recognizes strings with characters other than lower case a-z or numbers 0-9 as invalid alias strings', function () { | ||||
for (let i = 0; i < invalidAliasStrings.length; i += 1) { | for (let i = 0; i < invalidAliasStrings.length; i += 1) { | ||||
const invalidAliasString = invalidAliasStrings[i]; | const invalidAliasString = invalidAliasStrings[i]; | ||||
assert.deepEqual(isValidAliasString(invalidAliasString), false); | assert.deepEqual(isValidAliasString(invalidAliasString), false); | ||||
} | } | ||||
}); | }); | ||||
it('removeUnconfirmedTxsFromTxHistory removes unconfirmed txs from an array of chronik tx history', function () { | it('removeUnconfirmedTxsFromTxHistory removes unconfirmed txs from an array of chronik tx history', function () { | ||||
// First, clone the mock so that you are not modifying it in place | |||||
const txHistoryWithSomeUnconfirmedTxs = JSON.parse( | |||||
JSON.stringify(generated.txHistory), | |||||
); | |||||
// Then, delete the 'block' key of the most recent 3 txs | |||||
// NB these do not include valid alias registrations | |||||
delete txHistoryWithSomeUnconfirmedTxs[0].block; // db09c578d38f37bd9f2bb69eeb8ecb2e24c5be01aa2914f17d94759aadf71386 | |||||
delete txHistoryWithSomeUnconfirmedTxs[1].block; // c040ccdc46df2951b2ab0cd6d48cf9db7c518068d1f871e60379ee8ccd1caa0e | |||||
delete txHistoryWithSomeUnconfirmedTxs[2].block; // 828201e4680e6617636193d3f2a319daab80a8cc5772b9a5b6e068de639f2d9c | |||||
// Manually delete these txs from your expected result | |||||
let expectedResult = JSON.parse(JSON.stringify(generated.txHistory)); | |||||
expectedResult.splice(0, 3); | |||||
assert.deepEqual( | assert.deepEqual( | ||||
removeUnconfirmedTxsFromTxHistory( | removeUnconfirmedTxsFromTxHistory(txHistoryWithSomeUnconfirmedTxs), | ||||
unconfirmedAliasTxs.concat(testAddressAliases.txHistory), | expectedResult, | ||||
), | ); | ||||
testAddressAliases.txHistory, | }); | ||||
it('getNextPush returns a string of the requested hex byteCount and modifies the stack for both number and hexString type inputs for byteCount', function () { | |||||
const testHexString = | |||||
'6a042e78656300154361706974616c4c6574746572735f416e645f2b21150076458db0ed96fe9863fc1ccec9fa2cfab884b0f6'; | |||||
const stack = { remainingHex: testHexString }; | |||||
const firstPush = getNextPush(stack); // alias registration prefix | |||||
// getNextPush returns the push of testHexString | |||||
assert.strictEqual(firstPush, '2e786563'); | |||||
// Verify stack has been modified in place | |||||
assert.deepEqual(stack, { | |||||
remainingHex: | |||||
'00154361706974616c4c6574746572735f416e645f2b21150076458db0ed96fe9863fc1ccec9fa2cfab884b0f6', | |||||
}); | |||||
// alias tx version number | |||||
const secondPush = getNextPush(stack); | |||||
assert.strictEqual(secondPush, '00'); | |||||
// Verify stack has been modified in place | |||||
assert.deepEqual(stack, { | |||||
remainingHex: | |||||
'154361706974616c4c6574746572735f416e645f2b21150076458db0ed96fe9863fc1ccec9fa2cfab884b0f6', | |||||
}); | |||||
// alias | |||||
const thirdPush = getNextPush(stack); | |||||
assert.strictEqual( | |||||
thirdPush, | |||||
'4361706974616c4c6574746572735f416e645f2b21', | |||||
); | |||||
// Verify stack has been modified in place | |||||
assert.deepEqual(stack, { | |||||
remainingHex: '150076458db0ed96fe9863fc1ccec9fa2cfab884b0f6', | |||||
}); | |||||
// address type + hash | |||||
const fourthPush = getNextPush(stack); | |||||
assert.strictEqual( | |||||
fourthPush, | |||||
'0076458db0ed96fe9863fc1ccec9fa2cfab884b0f6', | |||||
); | |||||
// Verify stack has been modified in place | |||||
assert.deepEqual(stack, { | |||||
remainingHex: '', | |||||
}); | |||||
}); | |||||
it('getNextPush gets all pushes from a valid alias registration using OP_PUSHDATA1', function () { | |||||
const testHexString = | |||||
'6a4c042e786563004c154361706974616c4c6574746572735f416e645f2b214c150076458db0ed96fe9863fc1ccec9fa2cfab884b0f6'; | |||||
const stack = { remainingHex: testHexString }; | |||||
const firstPush = getNextPush(stack); // alias registration prefix | |||||
// getNextPush returns the push of testHexString | |||||
assert.strictEqual(firstPush, '2e786563'); | |||||
// Verify stack has been modified in place | |||||
assert.deepEqual(stack, { | |||||
remainingHex: | |||||
'004c154361706974616c4c6574746572735f416e645f2b214c150076458db0ed96fe9863fc1ccec9fa2cfab884b0f6', | |||||
}); | |||||
// alias tx version number | |||||
const secondPush = getNextPush(stack); | |||||
assert.strictEqual(secondPush, '00'); | |||||
// Verify stack has been modified in place | |||||
assert.deepEqual(stack, { | |||||
remainingHex: | |||||
'4c154361706974616c4c6574746572735f416e645f2b214c150076458db0ed96fe9863fc1ccec9fa2cfab884b0f6', | |||||
}); | |||||
// alias | |||||
const thirdPush = getNextPush(stack); | |||||
assert.strictEqual( | |||||
thirdPush, | |||||
'4361706974616c4c6574746572735f416e645f2b21', | |||||
); | |||||
// Verify stack has been modified in place | |||||
assert.deepEqual(stack, { | |||||
remainingHex: '4c150076458db0ed96fe9863fc1ccec9fa2cfab884b0f6', | |||||
}); | |||||
// address type + hash | |||||
const fourthPush = getNextPush(stack); | |||||
assert.strictEqual( | |||||
fourthPush, | |||||
'0076458db0ed96fe9863fc1ccec9fa2cfab884b0f6', | |||||
); | |||||
// Verify stack has been modified in place | |||||
assert.deepEqual(stack, { | |||||
remainingHex: '', | |||||
}); | |||||
}); | |||||
it('getNextPush gets all pushes from a valid alias registration using OP_PUSHDATA2', function () { | |||||
const testHexString = | |||||
'6a4d04002e786563004d15004361706974616c4c6574746572735f416e645f2b214d15000076458db0ed96fe9863fc1ccec9fa2cfab884b0f6'; | |||||
const stack = { remainingHex: testHexString }; | |||||
const firstPush = getNextPush(stack); // alias registration prefix | |||||
// getNextPush returns the push of testHexString | |||||
assert.strictEqual(firstPush, '2e786563'); | |||||
// Verify stack has been modified in place | |||||
assert.deepEqual(stack, { | |||||
remainingHex: | |||||
'004d15004361706974616c4c6574746572735f416e645f2b214d15000076458db0ed96fe9863fc1ccec9fa2cfab884b0f6', | |||||
}); | |||||
// alias tx version number | |||||
const secondPush = getNextPush(stack); | |||||
assert.strictEqual(secondPush, '00'); | |||||
// Verify stack has been modified in place | |||||
assert.deepEqual(stack, { | |||||
remainingHex: | |||||
'4d15004361706974616c4c6574746572735f416e645f2b214d15000076458db0ed96fe9863fc1ccec9fa2cfab884b0f6', | |||||
}); | |||||
// alias | |||||
const thirdPush = getNextPush(stack); | |||||
assert.strictEqual( | |||||
thirdPush, | |||||
'4361706974616c4c6574746572735f416e645f2b21', | |||||
); | |||||
// Verify stack has been modified in place | |||||
assert.deepEqual(stack, { | |||||
remainingHex: '4d15000076458db0ed96fe9863fc1ccec9fa2cfab884b0f6', | |||||
}); | |||||
// address type + hash | |||||
const fourthPush = getNextPush(stack); | |||||
assert.strictEqual( | |||||
fourthPush, | |||||
'0076458db0ed96fe9863fc1ccec9fa2cfab884b0f6', | |||||
); | |||||
// Verify stack has been modified in place | |||||
assert.deepEqual(stack, { | |||||
remainingHex: '', | |||||
}); | |||||
}); | |||||
it('getNextPush gets all pushes from a valid alias registration using OP_PUSHDATA4', function () { | |||||
const testHexString = | |||||
'6a4e040000002e786563004e150000004361706974616c4c6574746572735f416e645f2b214e150000000076458db0ed96fe9863fc1ccec9fa2cfab884b0f6'; | |||||
const stack = { remainingHex: testHexString }; | |||||
const firstPush = getNextPush(stack); // alias registration prefix | |||||
// getNextPush returns the push of testHexString | |||||
assert.strictEqual(firstPush, '2e786563'); | |||||
// Verify stack has been modified in place | |||||
assert.deepEqual(stack, { | |||||
remainingHex: | |||||
'004e150000004361706974616c4c6574746572735f416e645f2b214e150000000076458db0ed96fe9863fc1ccec9fa2cfab884b0f6', | |||||
}); | |||||
// alias tx version number | |||||
const secondPush = getNextPush(stack); | |||||
assert.strictEqual(secondPush, '00'); | |||||
// Verify stack has been modified in place | |||||
assert.deepEqual(stack, { | |||||
remainingHex: | |||||
'4e150000004361706974616c4c6574746572735f416e645f2b214e150000000076458db0ed96fe9863fc1ccec9fa2cfab884b0f6', | |||||
}); | |||||
// alias | |||||
const thirdPush = getNextPush(stack); | |||||
assert.strictEqual( | |||||
thirdPush, | |||||
'4361706974616c4c6574746572735f416e645f2b21', | |||||
); | |||||
// Verify stack has been modified in place | |||||
assert.deepEqual(stack, { | |||||
remainingHex: | |||||
'4e150000000076458db0ed96fe9863fc1ccec9fa2cfab884b0f6', | |||||
}); | |||||
// address type + hash | |||||
const fourthPush = getNextPush(stack); | |||||
assert.strictEqual( | |||||
fourthPush, | |||||
'0076458db0ed96fe9863fc1ccec9fa2cfab884b0f6', | |||||
); | ); | ||||
// Verify stack has been modified in place | |||||
assert.deepEqual(stack, { | |||||
remainingHex: '', | |||||
}); | |||||
}); | |||||
it('getNextPush returns OP_16 in one push', function () { | |||||
const testHexString = '6a60'; | |||||
const stack = { remainingHex: testHexString }; | |||||
const firstPush = getNextPush(stack); // alias registration prefix | |||||
// getNextPush returns the push of testHexString | |||||
assert.strictEqual(firstPush, '60'); | |||||
// Verify stack has been modified in place | |||||
assert.deepEqual(stack, { | |||||
remainingHex: '', | |||||
}); | |||||
}); | |||||
it('getNextPush throws expected error if the second byte of OP_PUSHDATA2 push is not 00', function () { | |||||
const testHexString = | |||||
'6a4d04042e786563004d15004361706974616c4c6574746572735f416e645f2b214d15000076458db0ed96fe9863fc1ccec9fa2cfab884b0f6'; | |||||
const stack = { remainingHex: testHexString }; | |||||
// getNextPush returns the push of testHexString | |||||
assert.throws(() => { | |||||
getNextPush(stack); | |||||
}, Error('Version 0 alias registrations cannot have pushdata > 255')); | |||||
// stack is unmodified | |||||
assert.deepEqual(stack, { | |||||
remainingHex: testHexString, | |||||
}); | |||||
}); | |||||
it('getNextPush throws expected error if the fourth byte of OP_PUSHDATA4 push is not 00', function () { | |||||
const testHexString = | |||||
'6a4e040000012e786563004d15004361706974616c4c6574746572735f416e645f2b214d15000076458db0ed96fe9863fc1ccec9fa2cfab884b0f6'; | |||||
const stack = { remainingHex: testHexString }; | |||||
// getNextPush returns the push of testHexString | |||||
assert.throws(() => { | |||||
getNextPush(stack); | |||||
}, Error('Version 0 alias registrations cannot have pushdata > 255')); | |||||
// stack is unmodified | |||||
assert.deepEqual(stack, { | |||||
remainingHex: testHexString, | |||||
}); | |||||
}); | |||||
it('getNextPush throws expected error if stack begins with invalid pushdata', function () { | |||||
const invalidPushdata = '61'; | |||||
const testHexString = `6a${invalidPushdata}042e786563`; | |||||
const stack = { remainingHex: testHexString }; | |||||
// getNextPush returns the push of testHexString | |||||
assert.throws(() => { | |||||
getNextPush(stack); | |||||
}, Error(`${invalidPushdata} is invalid pushdata`)); | |||||
// stack is unmodified | |||||
assert.deepEqual(stack, { | |||||
remainingHex: testHexString, | |||||
}); | |||||
}); | }); | ||||
}); | }); |