HookCanEmit (#22)

This commit is contained in:
tequ
2025-07-08 01:31:55 +09:00
committed by GitHub
parent 7a79042735
commit 83a25c6c34
6 changed files with 66 additions and 3 deletions

View File

@@ -1478,6 +1478,16 @@
"type": "Hash256" "type": "Hash256"
} }
], ],
[
"HookCanEmit",
{
"nth": 96,
"isVLEncoded": false,
"isSerialized": true,
"isSigningField": true,
"type": "Hash256"
}
],
[ [
"Amount", "Amount",
{ {

View File

@@ -63,6 +63,10 @@ export interface Hook {
* The transactions that triggers the hook. Represented as a 256Hash * The transactions that triggers the hook. Represented as a 256Hash
*/ */
HookOn?: string HookOn?: string
/**
* The transactions that can emit from the hook. Represented as a 256Hash
*/
HookCanEmit?: string
/** /**
* The namespace of the hook. * The namespace of the hook.
*/ */

View File

@@ -66,12 +66,17 @@ export function validateSetHook(tx: Record<string, unknown>): void {
for (const hook of tx.Hooks) { for (const hook of tx.Hooks) {
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- Should be a Hook // eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- Should be a Hook
const hookObject = hook as Hook const hookObject = hook as Hook
const { HookOn, HookNamespace } = hookObject.Hook const { HookOn, HookCanEmit, HookNamespace } = hookObject.Hook
if (HookOn !== undefined && !HEX_REGEX.test(HookOn)) { if (HookOn !== undefined && !HEX_REGEX.test(HookOn)) {
throw new ValidationError( throw new ValidationError(
`SetHook: HookOn in Hook must be a 256-bit (32-byte) hexadecimal value`, `SetHook: HookOn in Hook must be a 256-bit (32-byte) hexadecimal value`,
) )
} }
if (HookCanEmit !== undefined && !HEX_REGEX.test(HookCanEmit)) {
throw new ValidationError(
`SetHook: HookCanEmit in Hook must be a 256-bit (32-byte) hexadecimal value`,
)
}
if (HookNamespace !== undefined && !HEX_REGEX.test(HookNamespace)) { if (HookNamespace !== undefined && !HEX_REGEX.test(HookNamespace)) {
throw new ValidationError( throw new ValidationError(
`SetHook: HookNamespace in Hook must be a 256-bit (32-byte) hexadecimal value`, `SetHook: HookNamespace in Hook must be a 256-bit (32-byte) hexadecimal value`,

View File

@@ -55,6 +55,16 @@ export function calculateHookOn(arr: Array<keyof TTS>): string {
return hash.toUpperCase() return hash.toUpperCase()
} }
/**
* Calculate the hook can emit
*
* @param arr - array of transaction types
* @returns the hook can emit
*/
export function calculateHookCanEmit(arr: Array<keyof TTS>): string {
return calculateHookOn(arr)
}
function isHex(value: string): boolean { function isHex(value: string): boolean {
return /^[0-9A-F]+$/iu.test(value) return /^[0-9A-F]+$/iu.test(value)
} }

View File

@@ -46,7 +46,12 @@ import {
hashPaymentChannel, hashPaymentChannel,
hashURIToken, hashURIToken,
} from './hashes' } from './hashes'
import { calculateHookOn, hexHookParameters, TTS } from './hooks' import {
calculateHookOn,
calculateHookCanEmit,
hexHookParameters,
TTS,
} from './hooks'
import { import {
percentToTransferRate, percentToTransferRate,
decimalToTransferRate, decimalToTransferRate,
@@ -227,6 +232,7 @@ export {
encodeForSigning, encodeForSigning,
encodeForSigningClaim, encodeForSigningClaim,
calculateHookOn, calculateHookOn,
calculateHookCanEmit,
hexHookParameters, hexHookParameters,
TTS, TTS,
} }

View File

@@ -9,7 +9,7 @@ import { validateSetHook } from '../../src/models/transactions/setHook'
* Providing runtime verification testing for each specific transaction type. * Providing runtime verification testing for each specific transaction type.
*/ */
describe('SetHook', function () { describe('SetHook', function () {
let setHookTx let setHookTx: any
beforeEach(function () { beforeEach(function () {
setHookTx = { setHookTx = {
@@ -24,6 +24,8 @@ describe('SetHook', function () {
'0061736D01000000011C0460057F7F7F7F7F017E60037F7F7E017E60027F7F017F60017F017E02230303656E76057472616365000003656E7606616363657074000103656E76025F670002030201030503010002062B077F0141B088040B7F004180080B7F0041A6080B7F004180080B7F0041B088040B7F0041000B7F0041010B07080104686F6F6B00030AC4800001C0800001017F230041106B220124002001200036020C41920841134180084112410010001A410022002000420010011A41012200200010021A200141106A240042000B0B2C01004180080B254163636570742E633A2043616C6C65642E00224163636570742E633A2043616C6C65642E22', '0061736D01000000011C0460057F7F7F7F7F017E60037F7F7E017E60027F7F017F60017F017E02230303656E76057472616365000003656E7606616363657074000103656E76025F670002030201030503010002062B077F0141B088040B7F004180080B7F0041A6080B7F004180080B7F0041B088040B7F0041000B7F0041010B07080104686F6F6B00030AC4800001C0800001017F230041106B220124002001200036020C41920841134180084112410010001A410022002000420010011A41012200200010021A200141106A240042000B0B2C01004180080B254163636570742E633A2043616C6C65642E00224163636570742E633A2043616C6C65642E22',
HookOn: HookOn:
'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBFFFF7', 'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBFFFF7',
HookCanEmit:
'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBFFFF7',
Flags: 1, Flags: 1,
HookApiVersion: 0, HookApiVersion: 0,
HookNamespace: HookNamespace:
@@ -114,6 +116,32 @@ describe('SetHook', function () {
assert.throws(() => validate(setHookTx), ValidationError, errorMessage) assert.throws(() => validate(setHookTx), ValidationError, errorMessage)
}) })
it(`throws w/ invalid HookCanEmit in Hooks`, function () {
setHookTx.Hooks = [
{
Hook: {
CreateCode:
'0061736D01000000011C0460057F7F7F7F7F017E60037F7F7E017E60027F7F017F60017F017E02230303656E76057472616365000003656E7606616363657074000103656E76025F670002030201030503010002062B077F0141B088040B7F004180080B7F0041A6080B7F004180080B7F0041B088040B7F0041000B7F0041010B07080104686F6F6B00030AC4800001C0800001017F230041106B220124002001200036020C41920841134180084112410010001A410022002000420010011A41012200200010021A200141106A240042000B0B2C01004180080B254163636570742E633A2043616C6C65642E00224163636570742E633A2043616C6C65642E22',
HookOn:
'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBFFFF7',
HookCanEmit: '',
Flags: 1,
HookApiVersion: 0,
HookNamespace:
'4FF9961269BF7630D32E15276569C94470174A5DA79FA567C0F62251AA9A36B9',
},
},
]
const errorMessage =
'SetHook: HookCanEmit in Hook must be a 256-bit (32-byte) hexadecimal value'
assert.throws(
() => validateSetHook(setHookTx),
ValidationError,
errorMessage,
)
assert.throws(() => validate(setHookTx), ValidationError, errorMessage)
})
it(`throws w/ invalid HookNamespace in Hooks`, function () { it(`throws w/ invalid HookNamespace in Hooks`, function () {
setHookTx.SignerQuorum = 2 setHookTx.SignerQuorum = 2
setHookTx.Hooks = [ setHookTx.Hooks = [