mirror of
https://github.com/Xahau/xahau.js.git
synced 2025-11-26 15:15:49 +00:00
Export hashing functions (#1275)
The now-deprecated ripple-hashes library provided a number of hash functions for users to compute the hashes/IDs for various XRP Ledger objects: * Transactions (to generate transaction hashes, also known as IDs) * Transaction signing hashes (to sign transactions) * Ledger Object IDs (to look up specific ledger objects in a ledger's state tree; see https://xrpl.org/ledger-object-ids.html) This commit exports these utility methods from ripple-lib as static methods. Access them on the RippleAPI class. Example: import {RippleAPI} from 'ripple-lib' const hash = RippleAPI.computeBinaryTransactionHash(...)
This commit is contained in:
38
src/api.ts
38
src/api.ts
@@ -89,6 +89,19 @@ import {clamp, renameCounterpartyToIssuer} from './ledger/utils'
|
|||||||
import {TransactionJSON, Instructions, Prepare} from './transaction/types'
|
import {TransactionJSON, Instructions, Prepare} from './transaction/types'
|
||||||
import {ConnectionUserOptions} from './common/connection'
|
import {ConnectionUserOptions} from './common/connection'
|
||||||
import {isValidXAddress, isValidClassicAddress} from 'ripple-address-codec'
|
import {isValidXAddress, isValidClassicAddress} from 'ripple-address-codec'
|
||||||
|
import {
|
||||||
|
computeBinaryTransactionHash,
|
||||||
|
computeTransactionHash,
|
||||||
|
computeBinaryTransactionSigningHash,
|
||||||
|
computeAccountLedgerObjectID,
|
||||||
|
computeSignerListLedgerObjectID,
|
||||||
|
computeOrderID,
|
||||||
|
computeTrustlineHash,
|
||||||
|
computeTransactionTreeHash,
|
||||||
|
computeStateTreeHash,
|
||||||
|
computeEscrowHash,
|
||||||
|
computePaymentChannelHash
|
||||||
|
} from './common/hashes'
|
||||||
|
|
||||||
export interface APIOptions extends ConnectionUserOptions {
|
export interface APIOptions extends ConnectionUserOptions {
|
||||||
server?: string
|
server?: string
|
||||||
@@ -402,6 +415,31 @@ class RippleAPI extends EventEmitter {
|
|||||||
static isValidXAddress = isValidXAddress
|
static isValidXAddress = isValidXAddress
|
||||||
static isValidClassicAddress = isValidClassicAddress
|
static isValidClassicAddress = isValidClassicAddress
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Static methods that replace functionality from the now-deprecated ripple-hashes library
|
||||||
|
*/
|
||||||
|
// Compute the hash of a binary transaction blob.
|
||||||
|
static computeBinaryTransactionHash = computeBinaryTransactionHash // (txBlobHex: string): string
|
||||||
|
// Compute the hash of a transaction in txJSON format.
|
||||||
|
static computeTransactionHash = computeTransactionHash // (txJSON: any): string
|
||||||
|
static computeBinaryTransactionSigningHash = computeBinaryTransactionSigningHash // (txBlobHex: string): string
|
||||||
|
// Compute the hash of an account, given the account's classic address (starting with `r`).
|
||||||
|
static computeAccountLedgerObjectID = computeAccountLedgerObjectID // (address: string): string
|
||||||
|
// Compute the hash (ID) of an account's SignerList.
|
||||||
|
static computeSignerListLedgerObjectID = computeSignerListLedgerObjectID // (address: string): string
|
||||||
|
// Compute the hash of an order, given the owner's classic address (starting with `r`) and the account sequence number of the `OfferCreate` order transaction.
|
||||||
|
static computeOrderID = computeOrderID // (address: string, sequence: number): string
|
||||||
|
// Compute the hash of a trustline, given the two parties' classic addresses (starting with `r`) and the currency code.
|
||||||
|
static computeTrustlineHash = computeTrustlineHash // (address1: string, address2: string, currency: string): string
|
||||||
|
static computeTransactionTreeHash = computeTransactionTreeHash // (transactions: any[]): string
|
||||||
|
static computeStateTreeHash = computeStateTreeHash // (entries: any[]): string
|
||||||
|
// Compute the hash of a ledger.
|
||||||
|
static computeLedgerHash = computeLedgerHash // (ledgerHeader): string
|
||||||
|
// Compute the hash of an escrow, given the owner's classic address (starting with `r`) and the account sequence number of the `EscrowCreate` escrow transaction.
|
||||||
|
static computeEscrowHash = computeEscrowHash // (address, sequence): string
|
||||||
|
// Compute the hash of a payment channel, given the owner's classic address (starting with `r`), the classic address of the destination, and the account sequence number of the `PaymentChannelCreate` payment channel transaction.
|
||||||
|
static computePaymentChannelHash = computePaymentChannelHash // (address, dstAddress, sequence): string
|
||||||
|
|
||||||
xrpToDrops = xrpToDrops
|
xrpToDrops = xrpToDrops
|
||||||
dropsToXrp = dropsToXrp
|
dropsToXrp = dropsToXrp
|
||||||
rippleTimeToISO8601 = rippleTimeToISO8601
|
rippleTimeToISO8601 = rippleTimeToISO8601
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
Methods to hash XRP Ledger objects
|
Methods to hash XRP Ledger objects
|
||||||
|
|
||||||
## Methods
|
## Computing a transaction hash (ID)
|
||||||
|
|
||||||
### computeBinaryTransactionHash = (txBlobHex: string): string
|
### computeBinaryTransactionHash = (txBlobHex: string): string
|
||||||
|
|
||||||
@@ -12,19 +12,35 @@ Compute the hash of a binary transaction blob.
|
|||||||
|
|
||||||
Compute the hash of a transaction in txJSON format.
|
Compute the hash of a transaction in txJSON format.
|
||||||
|
|
||||||
|
## [Hash Prefixes](https://xrpl.org/basic-data-types.html#hash-prefixes)
|
||||||
|
|
||||||
|
In many cases, the XRP Ledger prefixes an object's binary data with a 4-byte code before calculating its hash, so that objects of different types have different hashes even if the binary data is the same. The existing 4-byte codes are structured as 3 alphabetic characters, encoded as ASCII, followed by a zero byte.
|
||||||
|
|
||||||
|
Some types of hashes appear in API requests and responses. Others are only calculated as the first step of signing a certain type of data, or calculating a higher-level hash. Some of following methods internally use some of the 4-byte hash prefixes in order to calculate the appropriate hash.
|
||||||
|
|
||||||
### computeBinaryTransactionSigningHash = (txBlobHex: string): string
|
### computeBinaryTransactionSigningHash = (txBlobHex: string): string
|
||||||
|
|
||||||
### computeTransactionSigningHash = (txJSON: any): string
|
In order to single-sign a transaction, you must perform these steps:
|
||||||
|
|
||||||
### computeAccountHash = (address: string): string
|
1. Assuming the transaction is in JSON format (txJSON), `encode` the transaction in the XRP Ledger's binary format.
|
||||||
|
2. Hash the data with the appropriate prefix (`0x53545800` if single-signing, or `0x534D5400` if multi-signing).
|
||||||
|
3. After signing, you must re-serialize the transaction with the `TxnSignature` field included.
|
||||||
|
|
||||||
|
The `computeBinaryTransactionSigningHash` helps with step 2, automatically using the `0x53545800` prefix needed for single-signing a transaction.
|
||||||
|
|
||||||
|
For details, see [Serialization Format](https://xrpl.org/serialization.html).
|
||||||
|
|
||||||
|
_Removed:_ `computeTransactionSigningHash`, which took txJSON as a parameter. It was part of the deprecated ripple-hashes library. If you have txJSON, `encode` it with [ripple-binary-codec](https://github.com/ripple/ripple-binary-codec) first. Example: `return computeBinaryTransactionSigningHash(encode(txJSON))`
|
||||||
|
|
||||||
|
### computeAccountLedgerObjectID = (address: string): string
|
||||||
|
|
||||||
Compute the hash of an account, given the account's classic address (starting with `r`).
|
Compute the hash of an account, given the account's classic address (starting with `r`).
|
||||||
|
|
||||||
### computeSignerListHash = (address: string): string
|
### computeSignerListLedgerObjectID = (address: string): string
|
||||||
|
|
||||||
Compute the hash of an account's SignerList.
|
Compute the hash of an account's SignerList.
|
||||||
|
|
||||||
### computeOrderHash = (address: string, sequence: number): string
|
### computeOrderID = (address: string, sequence: number): string
|
||||||
|
|
||||||
Compute the hash of an order, given the owner's classic address (starting with `r`) and the account sequence number of the `OfferCreate` order transaction.
|
Compute the hash of an order, given the owner's classic address (starting with `r`) and the account sequence number of the `OfferCreate` order transaction.
|
||||||
|
|
||||||
|
|||||||
@@ -71,6 +71,14 @@ export const computeTransactionHash = (txJSON: any): string => {
|
|||||||
return computeBinaryTransactionHash(encode(txJSON))
|
return computeBinaryTransactionHash(encode(txJSON))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hash the given binary transaction data with the single-signing prefix.
|
||||||
|
*
|
||||||
|
* See [Serialization Format](https://xrpl.org/serialization.html)
|
||||||
|
*
|
||||||
|
* @param txBlobHex The binary transaction blob as a hexadecimal string
|
||||||
|
* @returns {string} The hash to sign
|
||||||
|
*/
|
||||||
export const computeBinaryTransactionSigningHash = (
|
export const computeBinaryTransactionSigningHash = (
|
||||||
txBlobHex: string
|
txBlobHex: string
|
||||||
): string => {
|
): string => {
|
||||||
@@ -78,21 +86,56 @@ export const computeBinaryTransactionSigningHash = (
|
|||||||
return sha512Half(prefix + txBlobHex)
|
return sha512Half(prefix + txBlobHex)
|
||||||
}
|
}
|
||||||
|
|
||||||
export const computeTransactionSigningHash = (txJSON: any): string => {
|
/**
|
||||||
return computeBinaryTransactionSigningHash(encode(txJSON))
|
* Compute Account Ledger Object ID
|
||||||
}
|
*
|
||||||
|
* All objects in a ledger's state tree have a unique ID.
|
||||||
export const computeAccountHash = (address: string): string => {
|
* The Account Ledger Object ID is derived by hashing the
|
||||||
|
* address with a namespace identifier. This ensures every
|
||||||
|
* ID is unique.
|
||||||
|
*
|
||||||
|
* See [Ledger Object IDs](https://xrpl.org/ledger-object-ids.html)
|
||||||
|
*
|
||||||
|
* @param address The classic account address
|
||||||
|
* @returns {string} The Ledger Object ID for the account
|
||||||
|
*/
|
||||||
|
export const computeAccountLedgerObjectID = (address: string): string => {
|
||||||
return sha512Half(ledgerSpaceHex('account') + addressToHex(address))
|
return sha512Half(ledgerSpaceHex('account') + addressToHex(address))
|
||||||
}
|
}
|
||||||
|
|
||||||
export const computeSignerListHash = (address: string): string => {
|
/**
|
||||||
|
* [SignerList ID Format](https://xrpl.org/signerlist.html#signerlist-id-format)
|
||||||
|
*
|
||||||
|
* The ID of a SignerList object is the SHA-512Half of the following values, concatenated in order:
|
||||||
|
* * The RippleState space key (0x0053)
|
||||||
|
* * The AccountID of the owner of the SignerList
|
||||||
|
* * The SignerListID (currently always 0)
|
||||||
|
*
|
||||||
|
* This method computes a SignerList Ledger Object ID.
|
||||||
|
*
|
||||||
|
* @param address The classic account address of the SignerList owner (starting with r)
|
||||||
|
* @return {string} The ID of the account's SignerList object
|
||||||
|
*/
|
||||||
|
export const computeSignerListLedgerObjectID = (address: string): string => {
|
||||||
return sha512Half(
|
return sha512Half(
|
||||||
ledgerSpaceHex('signerList') + addressToHex(address) + '00000000'
|
ledgerSpaceHex('signerList') + addressToHex(address) + '00000000'
|
||||||
) // uint32(0) signer list index
|
) // uint32(0) signer list index
|
||||||
}
|
}
|
||||||
|
|
||||||
export const computeOrderHash = (address: string, sequence: number): string => {
|
/**
|
||||||
|
* [Offer ID Format](https://xrpl.org/offer.html#offer-id-format)
|
||||||
|
*
|
||||||
|
* The ID of a Offer object is the SHA-512Half of the following values, concatenated in order:
|
||||||
|
* * The Offer space key (0x006F)
|
||||||
|
* * The AccountID of the account placing the offer
|
||||||
|
* * The Sequence number of the OfferCreate transaction that created the offer
|
||||||
|
*
|
||||||
|
* This method computes an Offer ID (aka Order ID).
|
||||||
|
*
|
||||||
|
* @param address The classic account address of the SignerList owner (starting with r)
|
||||||
|
* @returns {string} The ID of the account's Offer object
|
||||||
|
*/
|
||||||
|
export const computeOrderID = (address: string, sequence: number): string => {
|
||||||
const prefix = '00' + intToHex(ledgerspaces.offer.charCodeAt(0), 1)
|
const prefix = '00' + intToHex(ledgerspaces.offer.charCodeAt(0), 1)
|
||||||
return sha512Half(prefix + addressToHex(address) + intToHex(sequence, 4))
|
return sha512Half(prefix + addressToHex(address) + intToHex(sequence, 4))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
/**
|
/**
|
||||||
* Ripple ledger namespace prefixes.
|
* XRP Ledger namespace prefixes.
|
||||||
*
|
*
|
||||||
* The Ripple ledger is a key-value store. In order to avoid name collisions,
|
* The XRP Ledger is a key-value store. In order to avoid name collisions,
|
||||||
* names are partitioned into namespaces.
|
* names are partitioned into namespaces.
|
||||||
*
|
*
|
||||||
* Each namespace is just a single character prefix.
|
* Each namespace is just a single character prefix.
|
||||||
|
*
|
||||||
|
* See [LedgerNameSpace enum](https://github.com/ripple/rippled/blob/master/src/ripple/protocol/LedgerFormats.h#L100)
|
||||||
*/
|
*/
|
||||||
export default {
|
export default {
|
||||||
account: 'a',
|
account: 'a',
|
||||||
@@ -16,9 +18,12 @@ export default {
|
|||||||
bookDir: 'B', // Directory of order books.
|
bookDir: 'B', // Directory of order books.
|
||||||
contract: 'c',
|
contract: 'c',
|
||||||
skipList: 's',
|
skipList: 's',
|
||||||
|
escrow: 'u',
|
||||||
amendment: 'f',
|
amendment: 'f',
|
||||||
feeSettings: 'e',
|
feeSettings: 'e',
|
||||||
|
ticket: 'T',
|
||||||
signerList: 'S',
|
signerList: 'S',
|
||||||
escrow: 'u',
|
paychan: 'x',
|
||||||
paychan: 'x'
|
check: 'C',
|
||||||
|
depositPreauth: 'p'
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ describe('Ledger', function() {
|
|||||||
var account = 'rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh'
|
var account = 'rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh'
|
||||||
var expectedEntryHash =
|
var expectedEntryHash =
|
||||||
'2B6AC232AA4C4BE41BF49D2459FA4A0347E1B543A4C92FCEE0821C0201E2E9A8'
|
'2B6AC232AA4C4BE41BF49D2459FA4A0347E1B543A4C92FCEE0821C0201E2E9A8'
|
||||||
var actualEntryHash = hashes.computeAccountHash(account)
|
var actualEntryHash = hashes.computeAccountLedgerObjectID(account)
|
||||||
|
|
||||||
assert.equal(actualEntryHash, expectedEntryHash)
|
assert.equal(actualEntryHash, expectedEntryHash)
|
||||||
})
|
})
|
||||||
@@ -105,18 +105,18 @@ describe('Ledger', function() {
|
|||||||
var sequence = 137
|
var sequence = 137
|
||||||
var expectedEntryHash =
|
var expectedEntryHash =
|
||||||
'03F0AED09DEEE74CEF85CD57A0429D6113507CF759C597BABB4ADB752F734CE3'
|
'03F0AED09DEEE74CEF85CD57A0429D6113507CF759C597BABB4ADB752F734CE3'
|
||||||
var actualEntryHash = hashes.computeOrderHash(account, sequence)
|
var actualEntryHash = hashes.computeOrderID(account, sequence)
|
||||||
|
|
||||||
assert.equal(actualEntryHash, expectedEntryHash)
|
assert.equal(actualEntryHash, expectedEntryHash)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('computeSignerListHash', function() {
|
describe('computeSignerListLedgerObjectID', function() {
|
||||||
it('will calculate the SignerList index for r32UufnaCGL82HubijgJGDmdE5hac7ZvLw', function() {
|
it('will calculate the SignerList index for r32UufnaCGL82HubijgJGDmdE5hac7ZvLw', function() {
|
||||||
var account = 'rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh'
|
var account = 'rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh'
|
||||||
var expectedEntryHash =
|
var expectedEntryHash =
|
||||||
'778365D5180F5DF3016817D1F318527AD7410D83F8636CF48C43E8AF72AB49BF'
|
'778365D5180F5DF3016817D1F318527AD7410D83F8636CF48C43E8AF72AB49BF'
|
||||||
var actualEntryHash = hashes.computeSignerListHash(account)
|
var actualEntryHash = hashes.computeSignerListLedgerObjectID(account)
|
||||||
assert.equal(actualEntryHash, expectedEntryHash)
|
assert.equal(actualEntryHash, expectedEntryHash)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user