mirror of
https://github.com/Xahau/xahau.js.git
synced 2025-11-04 13:05:49 +00:00
Refactoring existing hash utils and adding tests (#1557)
Write toHash utils and tests, then fix naming to match our standards of camelCase
This commit is contained in:
committed by
Mayukha Vadari
parent
ac66c2174a
commit
1115f17a3e
@@ -1,11 +1,11 @@
|
||||
import BigNumber from 'bignumber.js'
|
||||
import _ from 'lodash'
|
||||
import * as _ from 'lodash'
|
||||
import { decodeAccountID } from 'ripple-address-codec'
|
||||
import binary from 'ripple-binary-codec'
|
||||
import { JsonObject } from 'ripple-binary-codec/dist/types/serialized-type'
|
||||
|
||||
import { ValidationError } from '../common/errors'
|
||||
import { computeBinaryTransactionHash } from '../utils/hashes'
|
||||
import { computeSignedTransactionHash } from '../utils/hashes'
|
||||
|
||||
/**
|
||||
* The transactions should all be equal except for the 'Signers' field.
|
||||
@@ -75,7 +75,7 @@ function combine(signedTransactions: string[]): object {
|
||||
)
|
||||
return {
|
||||
signedTransaction,
|
||||
id: computeBinaryTransactionHash(signedTransaction),
|
||||
id: computeSignedTransactionHash(signedTransaction),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ import keypairs from 'ripple-keypairs'
|
||||
import type { Client, Wallet } from '..'
|
||||
import { ValidationError } from '../common/errors'
|
||||
import { xrpToDrops } from '../utils'
|
||||
import { computeBinaryTransactionHash } from '../utils/hashes'
|
||||
import { computeSignedTransactionHash } from '../utils/hashes'
|
||||
|
||||
import { SignOptions, KeyPair, TransactionJSON } from './types'
|
||||
|
||||
@@ -61,7 +61,7 @@ function signWithKeypair(
|
||||
checkTxSerialization(serialized, tx)
|
||||
return {
|
||||
signedTransaction: serialized,
|
||||
id: computeBinaryTransactionHash(serialized),
|
||||
id: computeSignedTransactionHash(serialized),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,41 +1,47 @@
|
||||
import BigNumber from 'bignumber.js'
|
||||
import { decodeAccountID } from 'ripple-address-codec'
|
||||
import { encode } from 'ripple-binary-codec'
|
||||
import { decode, encode } from 'ripple-binary-codec'
|
||||
|
||||
import { ValidationError } from '../../common/errors'
|
||||
import { Transaction } from '../../models/transactions'
|
||||
|
||||
import HashPrefix from './hashPrefix'
|
||||
import ledgerSpaces from './ledgerSpaces'
|
||||
import sha512Half from './sha512Half'
|
||||
import { SHAMap, NodeType } from './shamap'
|
||||
|
||||
const padLeftZero = (string: string, length: number): string => {
|
||||
const BITS_IN_HEX = 16
|
||||
const BYTE_LENGTH = 4
|
||||
|
||||
function padLeftZero(string: string, length: number): string {
|
||||
return Array(length - string.length + 1).join('0') + string
|
||||
}
|
||||
|
||||
const intToHex = (integer: number, byteLength: number): string => {
|
||||
return padLeftZero(Number(integer).toString(16), byteLength * 2)
|
||||
function intToHex(integer: number, byteLength: number): string {
|
||||
return padLeftZero(Number(integer).toString(BITS_IN_HEX), byteLength * 2)
|
||||
}
|
||||
|
||||
const bytesToHex = (bytes: number[]): string => {
|
||||
function bytesToHex(bytes: number[]): string {
|
||||
return Buffer.from(bytes).toString('hex')
|
||||
}
|
||||
|
||||
const bigintToHex = (
|
||||
function bigintToHex(
|
||||
integerString: string | number | BigNumber,
|
||||
byteLength: number,
|
||||
): string => {
|
||||
): string {
|
||||
const hex = new BigNumber(integerString).toString(16)
|
||||
return padLeftZero(hex, byteLength * 2)
|
||||
}
|
||||
|
||||
const ledgerSpaceHex = (name: string): string => {
|
||||
function ledgerSpaceHex(name: string): string {
|
||||
return intToHex(ledgerSpaces[name].charCodeAt(0), 2)
|
||||
}
|
||||
|
||||
const addressToHex = (address: string): string => {
|
||||
function addressToHex(address: string): string {
|
||||
return Buffer.from(decodeAccountID(address)).toString('hex')
|
||||
}
|
||||
|
||||
const currencyToHex = (currency: string): string => {
|
||||
function currencyToHex(currency: string): string {
|
||||
if (currency.length === 3) {
|
||||
const bytes = new Array(20 + 1).join('0').split('').map(parseFloat)
|
||||
bytes[12] = currency.charCodeAt(0) & 0xff
|
||||
@@ -46,29 +52,53 @@ const currencyToHex = (currency: string): string => {
|
||||
return currency
|
||||
}
|
||||
|
||||
const addLengthPrefix = (hex: string): string => {
|
||||
function addLengthPrefix(hex: string): string {
|
||||
const length = hex.length / 2
|
||||
if (length <= 192) {
|
||||
return bytesToHex([length]) + hex
|
||||
}
|
||||
if (length <= 12480) {
|
||||
const x = length - 193
|
||||
// eslint-disable-next-line no-bitwise -- adding a prefix to hex requires bitwise operations
|
||||
return bytesToHex([193 + (x >>> 8), x & 0xff]) + hex
|
||||
}
|
||||
if (length <= 918744) {
|
||||
const x = length - 12481
|
||||
// eslint-disable-next-line no-bitwise -- adding a prefix to hex requires bitwise operations
|
||||
return bytesToHex([241 + (x >>> 16), (x >>> 8) & 0xff, x & 0xff]) + hex
|
||||
}
|
||||
throw new Error('Variable integer overflow.')
|
||||
}
|
||||
|
||||
export const computeBinaryTransactionHash = (txBlobHex: string): string => {
|
||||
const prefix = HashPrefix.TRANSACTION_ID.toString(16).toUpperCase()
|
||||
return sha512Half(prefix + txBlobHex)
|
||||
}
|
||||
/**
|
||||
* Hashes the Transaction object as the ledger does. Throws if the transaction is unsigned.
|
||||
*
|
||||
* @param tx - A transaction to hash. Tx may be in binary blob form. Tx must be signed.
|
||||
* @returns A hash of tx.
|
||||
* @throws ValidationError if the Transaction is unsigned.
|
||||
*/
|
||||
|
||||
export const computeTransactionHash = (txJSON: any): string => {
|
||||
return computeBinaryTransactionHash(encode(txJSON))
|
||||
export function computeSignedTransactionHash(tx: Transaction | string): string {
|
||||
let txBlob
|
||||
let txObject
|
||||
if (typeof tx === 'string') {
|
||||
txBlob = tx
|
||||
txObject = decode(tx)
|
||||
} else {
|
||||
txBlob = encode(tx)
|
||||
txObject = tx
|
||||
}
|
||||
|
||||
if (
|
||||
txObject.TxnSignature === undefined &&
|
||||
(txObject.Signers === undefined ||
|
||||
txObject.Signers[0].Signer.TxnSignature === undefined)
|
||||
) {
|
||||
throw new ValidationError('The transaction must be signed to hash it.')
|
||||
}
|
||||
|
||||
const prefix = HashPrefix.TRANSACTION_ID.toString(16).toUpperCase()
|
||||
return sha512Half(prefix.concat(txBlob))
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -79,9 +109,7 @@ export const computeTransactionHash = (txJSON: any): string => {
|
||||
* @param txBlobHex - The binary transaction blob as a hexadecimal string.
|
||||
* @returns The hash to sign.
|
||||
*/
|
||||
export const computeBinaryTransactionSigningHash = (
|
||||
txBlobHex: string,
|
||||
): string => {
|
||||
export function computeBinaryTransactionSigningHash(txBlobHex: string): string {
|
||||
const prefix = HashPrefix.TRANSACTION_SIGN.toString(16).toUpperCase()
|
||||
return sha512Half(prefix + txBlobHex)
|
||||
}
|
||||
@@ -99,7 +127,7 @@ export const computeBinaryTransactionSigningHash = (
|
||||
* @param address - The classic account address.
|
||||
* @returns The Ledger Object Index for the account.
|
||||
*/
|
||||
export const computeAccountRootIndex = (address: string): string => {
|
||||
export function computeAccountRootIndex(address: string): string {
|
||||
return sha512Half(ledgerSpaceHex('account') + addressToHex(address))
|
||||
}
|
||||
|
||||
@@ -116,7 +144,7 @@ export const computeAccountRootIndex = (address: string): string => {
|
||||
* @param address - The classic account address of the SignerList owner (starting with r).
|
||||
* @returns The ID of the account's SignerList object.
|
||||
*/
|
||||
export const computeSignerListIndex = (address: string): string => {
|
||||
export function computeSignerListIndex(address: string): string {
|
||||
return sha512Half(
|
||||
`${ledgerSpaceHex('signerList') + addressToHex(address)}00000000`,
|
||||
) // uint32(0) signer list index
|
||||
@@ -136,19 +164,16 @@ export const computeSignerListIndex = (address: string): string => {
|
||||
* @param sequence
|
||||
* @returns The index of the account's Offer object.
|
||||
*/
|
||||
export const computeOfferIndex = (
|
||||
address: string,
|
||||
sequence: number,
|
||||
): string => {
|
||||
export function computeOfferIndex(address: string, sequence: number): string {
|
||||
const prefix = `00${intToHex(ledgerSpaces.offer.charCodeAt(0), 1)}`
|
||||
return sha512Half(prefix + addressToHex(address) + intToHex(sequence, 4))
|
||||
}
|
||||
|
||||
export const computeTrustlineHash = (
|
||||
export function computeTrustlineHash(
|
||||
address1: string,
|
||||
address2: string,
|
||||
currency: string,
|
||||
): string => {
|
||||
): string {
|
||||
const address1Hex = addressToHex(address1)
|
||||
const address2Hex = addressToHex(address2)
|
||||
|
||||
@@ -164,13 +189,13 @@ export const computeTrustlineHash = (
|
||||
)
|
||||
}
|
||||
|
||||
export const computeTransactionTreeHash = (transactions: any[]): string => {
|
||||
export function computeTransactionTreeHash(transactions: any[]): string {
|
||||
const shamap = new SHAMap()
|
||||
|
||||
transactions.forEach((txJSON) => {
|
||||
const txBlobHex = encode(txJSON)
|
||||
const metaHex = encode(txJSON.metaData)
|
||||
const txHash = computeBinaryTransactionHash(txBlobHex)
|
||||
const txHash = computeSignedTransactionHash(txBlobHex)
|
||||
const data = addLengthPrefix(txBlobHex) + addLengthPrefix(metaHex)
|
||||
shamap.addItem(txHash, data, NodeType.TRANSACTION_METADATA)
|
||||
})
|
||||
@@ -178,7 +203,7 @@ export const computeTransactionTreeHash = (transactions: any[]): string => {
|
||||
return shamap.hash
|
||||
}
|
||||
|
||||
export const computeStateTreeHash = (entries: any[]): string => {
|
||||
export function computeStateTreeHash(entries: any[]): string {
|
||||
const shamap = new SHAMap()
|
||||
|
||||
entries.forEach((ledgerEntry) => {
|
||||
@@ -189,8 +214,8 @@ export const computeStateTreeHash = (entries: any[]): string => {
|
||||
return shamap.hash
|
||||
}
|
||||
|
||||
// see rippled Ledger::updateHash()
|
||||
export const computeLedgerHash = (ledgerHeader): string => {
|
||||
// see rippled Ledger::calculateLedgerHash()
|
||||
export function computeLedgerHash(ledgerHeader): string {
|
||||
const prefix = HashPrefix.LEDGER.toString(16).toUpperCase()
|
||||
return sha512Half(
|
||||
prefix +
|
||||
@@ -206,21 +231,23 @@ export const computeLedgerHash = (ledgerHeader): string => {
|
||||
)
|
||||
}
|
||||
|
||||
export const computeEscrowHash = (address, sequence): string => {
|
||||
export function computeEscrowHash(address: string, sequence: number): string {
|
||||
return sha512Half(
|
||||
ledgerSpaceHex('escrow') + addressToHex(address) + intToHex(sequence, 4),
|
||||
ledgerSpaceHex('escrow') +
|
||||
addressToHex(address) +
|
||||
intToHex(sequence, BYTE_LENGTH),
|
||||
)
|
||||
}
|
||||
|
||||
export const computePaymentChannelHash = (
|
||||
address,
|
||||
dstAddress,
|
||||
sequence,
|
||||
): string => {
|
||||
export function computePaymentChannelHash(
|
||||
address: string,
|
||||
dstAddress: string,
|
||||
sequence: number,
|
||||
): string {
|
||||
return sha512Half(
|
||||
ledgerSpaceHex('paychan') +
|
||||
addressToHex(address) +
|
||||
addressToHex(dstAddress) +
|
||||
intToHex(sequence, 4),
|
||||
intToHex(sequence, BYTE_LENGTH),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -8,8 +8,7 @@ import { RippledAmount } from '../common/types/objects'
|
||||
import { deriveKeypair, deriveAddress, deriveXAddress } from './derive'
|
||||
import { generateXAddress } from './generateAddress'
|
||||
import {
|
||||
computeBinaryTransactionHash,
|
||||
computeTransactionHash,
|
||||
computeSignedTransactionHash,
|
||||
computeBinaryTransactionSigningHash,
|
||||
computeAccountRootIndex,
|
||||
computeSignerListIndex,
|
||||
@@ -224,8 +223,7 @@ export {
|
||||
rippleTimeToISOTime,
|
||||
ISOTimeToRippleTime,
|
||||
isValidSecret,
|
||||
computeBinaryTransactionHash,
|
||||
computeTransactionHash,
|
||||
computeSignedTransactionHash,
|
||||
computeBinaryTransactionSigningHash,
|
||||
computeAccountRootIndex,
|
||||
computeSignerListIndex,
|
||||
|
||||
@@ -31,7 +31,7 @@ function hashLedgerHeader(ledgerHeader) {
|
||||
return computeLedgerHash(header)
|
||||
}
|
||||
|
||||
function computeTransactionHash(
|
||||
function computeLedgerTransactionHash(
|
||||
ledger,
|
||||
options: ComputeLedgerHeaderHashOptions,
|
||||
) {
|
||||
@@ -86,7 +86,10 @@ function computeTransactionHash(
|
||||
return transactionHash
|
||||
}
|
||||
|
||||
function computeStateHash(ledger, options: ComputeLedgerHeaderHashOptions) {
|
||||
function computeLedgerStateHash(
|
||||
ledger,
|
||||
options: ComputeLedgerHeaderHashOptions,
|
||||
) {
|
||||
if (ledger.rawState == null) {
|
||||
if (options.computeTreeHashes) {
|
||||
throw new ValidationError(
|
||||
@@ -114,8 +117,8 @@ function computeLedgerHeaderHash(
|
||||
options: ComputeLedgerHeaderHashOptions = {},
|
||||
): string {
|
||||
const subhashes = {
|
||||
transactionHash: computeTransactionHash(ledger, options),
|
||||
stateHash: computeStateHash(ledger, options),
|
||||
transactionHash: computeLedgerTransactionHash(ledger, options),
|
||||
stateHash: computeLedgerStateHash(ledger, options),
|
||||
}
|
||||
return hashLedgerHeader({ ...ledger, ...subhashes })
|
||||
}
|
||||
|
||||
@@ -1,17 +1,25 @@
|
||||
import assert from 'assert'
|
||||
import fs from 'fs'
|
||||
import { join } from 'path'
|
||||
import path from 'path'
|
||||
|
||||
import { assert } from 'chai'
|
||||
import { encode } from 'ripple-binary-codec'
|
||||
|
||||
import { ValidationError } from 'xrpl-local/common/errors'
|
||||
|
||||
import { OfferCreate, Transaction } from '../../src/models/transactions'
|
||||
import {
|
||||
computeStateTreeHash,
|
||||
computeTransactionTreeHash,
|
||||
computeAccountRootIndex,
|
||||
computeTrustlineHash,
|
||||
computeOfferIndex,
|
||||
computeSignerListIndex,
|
||||
computeEscrowHash,
|
||||
computePaymentChannelHash,
|
||||
computeSignedTransactionHash,
|
||||
computeAccountRootIndex,
|
||||
computeOfferIndex,
|
||||
computeSignerListIndex,
|
||||
} from '../../src/utils/hashes'
|
||||
import fixtures from '../fixtures/rippled'
|
||||
import { assertResultMatch } from '../testUtils'
|
||||
|
||||
/**
|
||||
* Expects a corresponding ledger dump in $repo/test/fixtures/rippled folder.
|
||||
@@ -20,14 +28,14 @@ import {
|
||||
*/
|
||||
function createLedgerTest(ledgerIndex: number): void {
|
||||
const ledgerIndexString = String(ledgerIndex)
|
||||
const path = join(
|
||||
const fileLocation = path.join(
|
||||
__dirname,
|
||||
'..',
|
||||
`fixtures/rippled/ledgerFull${ledgerIndex}.json`,
|
||||
)
|
||||
|
||||
// eslint-disable-next-line node/no-sync -- must be sync version when not in async method
|
||||
const ledgerRaw = fs.readFileSync(path, { encoding: 'utf8' })
|
||||
const ledgerRaw = fs.readFileSync(fileLocation, { encoding: 'utf8' })
|
||||
const ledgerJSON = JSON.parse(ledgerRaw)
|
||||
|
||||
const hasAccounts =
|
||||
@@ -64,111 +72,129 @@ describe('Hashes', function () {
|
||||
// eslint-disable-next-line mocha/no-setup-in-describe -- runs tests
|
||||
createLedgerTest(7501326)
|
||||
|
||||
describe('calcAccountRootEntryHash', function () {
|
||||
it('will calculate the AccountRoot entry hash for rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh', function () {
|
||||
const account = 'rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh'
|
||||
const expectedEntryHash =
|
||||
'2B6AC232AA4C4BE41BF49D2459FA4A0347E1B543A4C92FCEE0821C0201E2E9A8'
|
||||
const actualEntryHash = computeAccountRootIndex(account)
|
||||
it('calcAccountRootEntryHash', function () {
|
||||
const account = 'rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh'
|
||||
const expectedEntryHash =
|
||||
'2B6AC232AA4C4BE41BF49D2459FA4A0347E1B543A4C92FCEE0821C0201E2E9A8'
|
||||
const actualEntryHash = computeAccountRootIndex(account)
|
||||
|
||||
assert.equal(actualEntryHash, expectedEntryHash)
|
||||
})
|
||||
assert.equal(actualEntryHash, expectedEntryHash)
|
||||
})
|
||||
|
||||
describe('calcRippleStateEntryHash', function () {
|
||||
it('will calculate the RippleState entry hash for rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh and rB5TihdPbKgMrkFqrqUC3yLdE8hhv4BdeY in USD', function () {
|
||||
const account1 = 'rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh'
|
||||
const account2 = 'rB5TihdPbKgMrkFqrqUC3yLdE8hhv4BdeY'
|
||||
const currency = 'USD'
|
||||
it('calcRippleStateEntryHash', function () {
|
||||
const account1 = 'rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh'
|
||||
const account2 = 'rB5TihdPbKgMrkFqrqUC3yLdE8hhv4BdeY'
|
||||
const currency = 'USD'
|
||||
|
||||
const expectedEntryHash =
|
||||
'C683B5BB928F025F1E860D9D69D6C554C2202DE0D45877ADB3077DA4CB9E125C'
|
||||
const actualEntryHash1 = computeTrustlineHash(
|
||||
account1,
|
||||
account2,
|
||||
currency,
|
||||
)
|
||||
const actualEntryHash2 = computeTrustlineHash(
|
||||
account2,
|
||||
account1,
|
||||
currency,
|
||||
)
|
||||
const expectedEntryHash =
|
||||
'C683B5BB928F025F1E860D9D69D6C554C2202DE0D45877ADB3077DA4CB9E125C'
|
||||
const actualEntryHash1 = computeTrustlineHash(account1, account2, currency)
|
||||
const actualEntryHash2 = computeTrustlineHash(account2, account1, currency)
|
||||
|
||||
assert.equal(actualEntryHash1, expectedEntryHash)
|
||||
assert.equal(actualEntryHash2, expectedEntryHash)
|
||||
})
|
||||
|
||||
it('will calculate the RippleState entry hash for r3kmLJN5D28dHuH8vZNUZpMC43pEHpaocV and rUAMuQTfVhbfqUDuro7zzy4jj4Wq57MPTj in UAM', function () {
|
||||
const account1 = 'r3kmLJN5D28dHuH8vZNUZpMC43pEHpaocV'
|
||||
const account2 = 'rUAMuQTfVhbfqUDuro7zzy4jj4Wq57MPTj'
|
||||
const currency = 'UAM'
|
||||
|
||||
const expectedEntryHash =
|
||||
'AE9ADDC584358E5847ADFC971834E471436FC3E9DE6EA1773DF49F419DC0F65E'
|
||||
const actualEntryHash1 = computeTrustlineHash(
|
||||
account1,
|
||||
account2,
|
||||
currency,
|
||||
)
|
||||
const actualEntryHash2 = computeTrustlineHash(
|
||||
account2,
|
||||
account1,
|
||||
currency,
|
||||
)
|
||||
|
||||
assert.equal(actualEntryHash1, expectedEntryHash)
|
||||
assert.equal(actualEntryHash2, expectedEntryHash)
|
||||
})
|
||||
assert.equal(actualEntryHash1, expectedEntryHash)
|
||||
assert.equal(actualEntryHash2, expectedEntryHash)
|
||||
})
|
||||
|
||||
describe('calcOfferEntryHash', function () {
|
||||
it('will calculate the Offer entry hash for r32UufnaCGL82HubijgJGDmdE5hac7ZvLw, sequence 137', function () {
|
||||
const account = 'r32UufnaCGL82HubijgJGDmdE5hac7ZvLw'
|
||||
const sequence = 137
|
||||
const expectedEntryHash =
|
||||
'03F0AED09DEEE74CEF85CD57A0429D6113507CF759C597BABB4ADB752F734CE3'
|
||||
const actualEntryHash = computeOfferIndex(account, sequence)
|
||||
it('will calculate the RippleState entry hash for r3kmLJN5D28dHuH8vZNUZpMC43pEHpaocV and rUAMuQTfVhbfqUDuro7zzy4jj4Wq57MPTj in UAM', function () {
|
||||
const account1 = 'r3kmLJN5D28dHuH8vZNUZpMC43pEHpaocV'
|
||||
const account2 = 'rUAMuQTfVhbfqUDuro7zzy4jj4Wq57MPTj'
|
||||
const currency = 'UAM'
|
||||
|
||||
assert.equal(actualEntryHash, expectedEntryHash)
|
||||
})
|
||||
const expectedEntryHash =
|
||||
'AE9ADDC584358E5847ADFC971834E471436FC3E9DE6EA1773DF49F419DC0F65E'
|
||||
const actualEntryHash1 = computeTrustlineHash(account1, account2, currency)
|
||||
const actualEntryHash2 = computeTrustlineHash(account2, account1, currency)
|
||||
|
||||
assert.equal(actualEntryHash1, expectedEntryHash)
|
||||
assert.equal(actualEntryHash2, expectedEntryHash)
|
||||
})
|
||||
|
||||
describe('computeSignerListIndex', function () {
|
||||
it('will calculate the SignerList index for r32UufnaCGL82HubijgJGDmdE5hac7ZvLw', function () {
|
||||
const account = 'rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh'
|
||||
const expectedEntryHash =
|
||||
'778365D5180F5DF3016817D1F318527AD7410D83F8636CF48C43E8AF72AB49BF'
|
||||
const actualEntryHash = computeSignerListIndex(account)
|
||||
assert.equal(actualEntryHash, expectedEntryHash)
|
||||
})
|
||||
it('calcOfferEntryHash', function () {
|
||||
const account = 'r32UufnaCGL82HubijgJGDmdE5hac7ZvLw'
|
||||
const sequence = 137
|
||||
const expectedEntryHash =
|
||||
'03F0AED09DEEE74CEF85CD57A0429D6113507CF759C597BABB4ADB752F734CE3'
|
||||
const actualEntryHash = computeOfferIndex(account, sequence)
|
||||
|
||||
assert.equal(actualEntryHash, expectedEntryHash)
|
||||
})
|
||||
|
||||
describe('calcEscrowEntryHash', function () {
|
||||
it('will calculate the Escrow entry hash for rDx69ebzbowuqztksVDmZXjizTd12BVr4x, sequence 84', function () {
|
||||
const account = 'rDx69ebzbowuqztksVDmZXjizTd12BVr4x'
|
||||
const sequence = 84
|
||||
const expectedEntryHash =
|
||||
'61E8E8ED53FA2CEBE192B23897071E9A75217BF5A410E9CB5B45AAB7AECA567A'
|
||||
const actualEntryHash = computeEscrowHash(account, sequence)
|
||||
|
||||
assert.equal(actualEntryHash, expectedEntryHash)
|
||||
})
|
||||
it('computeSignerListIndex', function () {
|
||||
const account = 'rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh'
|
||||
const expectedEntryHash =
|
||||
'778365D5180F5DF3016817D1F318527AD7410D83F8636CF48C43E8AF72AB49BF'
|
||||
const actualEntryHash = computeSignerListIndex(account)
|
||||
assert.equal(actualEntryHash, expectedEntryHash)
|
||||
})
|
||||
|
||||
describe('calcPaymentChannelEntryHash', function () {
|
||||
it('will calculate the PaymentChannel entry hash for rDx69ebzbowuqztksVDmZXjizTd12BVr4x and rLFtVprxUEfsH54eCWKsZrEQzMDsx1wqso, sequence 82', function () {
|
||||
const account = 'rDx69ebzbowuqztksVDmZXjizTd12BVr4x'
|
||||
const dstAccount = 'rLFtVprxUEfsH54eCWKsZrEQzMDsx1wqso'
|
||||
const sequence = 82
|
||||
const expectedEntryHash =
|
||||
'E35708503B3C3143FB522D749AAFCC296E8060F0FB371A9A56FAE0B1ED127366'
|
||||
const actualEntryHash = computePaymentChannelHash(
|
||||
account,
|
||||
dstAccount,
|
||||
sequence,
|
||||
)
|
||||
it('calcEscrowEntryHash', function () {
|
||||
const account = 'rDx69ebzbowuqztksVDmZXjizTd12BVr4x'
|
||||
const sequence = 84
|
||||
const expectedEntryHash =
|
||||
'61E8E8ED53FA2CEBE192B23897071E9A75217BF5A410E9CB5B45AAB7AECA567A'
|
||||
const actualEntryHash = computeEscrowHash(account, sequence)
|
||||
|
||||
assert.equal(actualEntryHash, expectedEntryHash)
|
||||
assert.equal(actualEntryHash, expectedEntryHash)
|
||||
})
|
||||
|
||||
it('calcPaymentChannelEntryHash', function () {
|
||||
const account = 'rDx69ebzbowuqztksVDmZXjizTd12BVr4x'
|
||||
const dstAccount = 'rLFtVprxUEfsH54eCWKsZrEQzMDsx1wqso'
|
||||
const sequence = 82
|
||||
const expectedEntryHash =
|
||||
'E35708503B3C3143FB522D749AAFCC296E8060F0FB371A9A56FAE0B1ED127366'
|
||||
const actualEntryHash = computePaymentChannelHash(
|
||||
account,
|
||||
dstAccount,
|
||||
sequence,
|
||||
)
|
||||
|
||||
assert.equal(actualEntryHash, expectedEntryHash)
|
||||
})
|
||||
|
||||
it('Hash a signed transaction correctly', function () {
|
||||
const expected_hash =
|
||||
'458101D51051230B1D56E9ACAFAA34451BF65FA000F95DF6F0FF5B3A62D83FC2'
|
||||
|
||||
assertResultMatch(
|
||||
computeSignedTransactionHash(
|
||||
fixtures.tx.OfferCreateSell.result as Transaction,
|
||||
),
|
||||
expected_hash,
|
||||
)
|
||||
})
|
||||
|
||||
it('Hash a signed transaction blob correctly', function () {
|
||||
const expected_hash =
|
||||
'458101D51051230B1D56E9ACAFAA34451BF65FA000F95DF6F0FF5B3A62D83FC2'
|
||||
|
||||
assertResultMatch(
|
||||
computeSignedTransactionHash(encode(fixtures.tx.OfferCreateSell.result)),
|
||||
expected_hash,
|
||||
)
|
||||
})
|
||||
|
||||
it('Throw an error when hashing an unsigned transaction', function () {
|
||||
const offerCreateWithNoSignature: OfferCreate = {
|
||||
...(fixtures.tx.OfferCreateSell.result as OfferCreate),
|
||||
TxnSignature: undefined,
|
||||
}
|
||||
|
||||
assert.throws(
|
||||
() => computeSignedTransactionHash(offerCreateWithNoSignature),
|
||||
ValidationError,
|
||||
)
|
||||
})
|
||||
|
||||
it('Throw when hashing an unsigned transaction blob', function () {
|
||||
const encodedOfferCreateWithNoSignature: string = encode({
|
||||
...fixtures.tx.OfferCreateSell.result,
|
||||
TxnSignature: undefined,
|
||||
})
|
||||
|
||||
assert.throws(
|
||||
() => computeSignedTransactionHash(encodedOfferCreateWithNoSignature),
|
||||
ValidationError,
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user