Skip to content

Commit 548df89

Browse files
committed
Continue BCH_2026 development
1 parent cea3f0f commit 548df89

File tree

86 files changed

+7653
-2510
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

86 files changed

+7653
-2510
lines changed

.cspell.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@
6969
"deserialize",
7070
"devtools",
7171
"discoverability",
72+
"DIVSHIFT",
7273
"Dreyzehner",
7374
"DYNAMICTOP",
7475
"ecdsa",
@@ -112,6 +113,7 @@
112113
"MINIMALIF",
113114
"MITM",
114115
"monospace",
116+
"MULSHIFT",
115117
"multisig",
116118
"Nakamoto",
117119
"NONFUNGIBLE",
@@ -130,6 +132,8 @@
130132
"OUTPUTTOKENCATEGORY",
131133
"OUTPUTTOKENCOMMITMENT",
132134
"OUTPUTVALUE",
135+
"PADLEFT",
136+
"PADRIGHT",
133137
"parsimmon",
134138
"performant",
135139
"plusplus",

src/lib/message/fixtures/token-prefix-valid.json

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -607,6 +607,17 @@
607607
}
608608
}
609609
},
610+
{
611+
"prefix": "efbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb7280ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccffffffffffffffff7f",
612+
"data": {
613+
"amount": "9223372036854775807",
614+
"category": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
615+
"nft": {
616+
"commitment": "cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc",
617+
"capability": "minting"
618+
}
619+
}
620+
},
610621
{
611622
"prefix": "efbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb62fdfd00cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc",
612623
"data": {

src/lib/schema/ajv/validate-bcmr.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ const schema22 = {
3030
},
3131
splitId: {
3232
description:
33-
"The split ID of this identity's chain of record.\n\nIf undefined, defaults to {@link MetadataRegistry.defaultChain } .",
33+
'The split ID of this identity\'s chain of record.\n\nIf undefined, defaults to {@link MetadataRegistry.defaultChain } .\n\nTODO: rename "splitId" to "chainBranchId" (more clearly refers to the immediate descendent of the split block)',
3434
type: 'string',
3535
},
3636
status: {
@@ -123,7 +123,7 @@ const schema22 = {
123123
},
124124
splitId: {
125125
description:
126-
"The split ID of this identity's chain of record.\n\nIf undefined, defaults to {@link MetadataRegistry.defaultChain } .",
126+
'The split ID of this identity\'s chain of record.\n\nIf undefined, defaults to {@link MetadataRegistry.defaultChain } .\n\nTODO: rename "splitId" to "chainBranchId" (more clearly refers to the immediate descendent of the split block)',
127127
type: 'string',
128128
},
129129
status: {
@@ -665,7 +665,7 @@ const schema25 = {
665665
},
666666
splitId: {
667667
description:
668-
"The split ID of this identity's chain of record.\n\nIf undefined, defaults to {@link MetadataRegistry.defaultChain } .",
668+
'The split ID of this identity\'s chain of record.\n\nIf undefined, defaults to {@link MetadataRegistry.defaultChain } .\n\nTODO: rename "splitId" to "chainBranchId" (more clearly refers to the immediate descendent of the split block)',
669669
type: 'string',
670670
},
671671
status: {
@@ -1440,7 +1440,7 @@ const schema30 = {
14401440
},
14411441
splitId: {
14421442
description:
1443-
"The split ID of this identity's chain of record.\n\nIf undefined, defaults to {@link MetadataRegistry.defaultChain } .",
1443+
'The split ID of this identity\'s chain of record.\n\nIf undefined, defaults to {@link MetadataRegistry.defaultChain } .\n\nTODO: rename "splitId" to "chainBranchId" (more clearly refers to the immediate descendent of the split block)',
14441444
type: 'string',
14451445
},
14461446
status: {

src/lib/schema/bcmr.schema.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
"type": "string"
2424
},
2525
"splitId": {
26-
"description": "The split ID of this identity's chain of record.\n\nIf undefined, defaults to {@link MetadataRegistry.defaultChain } .",
26+
"description": "The split ID of this identity's chain of record.\n\nIf undefined, defaults to {@link MetadataRegistry.defaultChain } .\n\nTODO: rename \"splitId\" to \"chainBranchId\" (more clearly refers to the immediate descendent of the split block)",
2727
"type": "string"
2828
},
2929
"status": {
@@ -113,7 +113,7 @@
113113
"type": "string"
114114
},
115115
"splitId": {
116-
"description": "The split ID of this identity's chain of record.\n\nIf undefined, defaults to {@link MetadataRegistry.defaultChain } .",
116+
"description": "The split ID of this identity's chain of record.\n\nIf undefined, defaults to {@link MetadataRegistry.defaultChain } .\n\nTODO: rename \"splitId\" to \"chainBranchId\" (more clearly refers to the immediate descendent of the split block)",
117117
"type": "string"
118118
},
119119
"status": {

src/lib/vm/instruction-sets/bch/2023/bch-2023-instruction-set.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -419,10 +419,12 @@ export const createInstructionSetBch2023 = <
419419
return {
420420
alternateStack: [],
421421
controlStack: [],
422+
functionTable: [],
422423
ip: 0,
423424
lastCodeSeparator: -1,
424425
metrics: {
425426
arithmeticCost: 0,
427+
definedFunctions: 0,
426428
densityControlLength,
427429
evaluatedInstructionCount: 0,
428430
hashDigestIterations: 0,

src/lib/vm/instruction-sets/bch/2026/bch-2026-consensus.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,11 @@ import { ConsensusBch2025 } from '../2025/bch-2025-consensus.js';
55
*/
66
// eslint-disable-next-line @typescript-eslint/naming-convention
77
export const ConsensusBch2026Overrides = {
8+
maximumFunctionIdentifier: 999,
89
maximumStandardLockingBytecodeLength: 201,
910
maximumStandardUnlockingBytecodeLength: 10000,
1011
maximumTokenCommitmentLength: 128,
12+
minimumFunctionIdentifier: 0,
1113
};
1214

1315
/**

src/lib/vm/instruction-sets/bch/2026/bch-2026-descriptions.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,14 @@ import { OpcodeDescriptionsBch2023 } from '../2023/bch-2023-descriptions.js';
55
* beyond those present in `BCH_2025_05`.
66
*/
77
export enum OpcodeDescriptionsBch2026Additions {
8-
OP_EVAL = 'Pop the top item from the stack as bytecode. Preserve the active bytecode at the top of the control stack, then evaluate the stack-provided bytecode as if it were the active bytecode (without modifying the stack, alternate stack, or other evaluation context). When the evaluation is complete, restore the original bytecode and continue evaluation after the OP_EVAL instruction. If the bytecode is malformed, error.',
98
OP_BEGIN = 'Push the current instruction pointer index to the control stack as an integer (to be read by OP_UNTIL).',
109
OP_UNTIL = 'Pop the top item from the control stack (if the control value is not an integer, error). Add the difference between the control value and the current instruction pointer index to the repeated bytes counter, if the sum of the repeated bytes counter and the active bytecode length is greater than the maximum bytecode length, error. Pop the top item from the stack, if the value is not truthy, move the instruction pointer to the control value (and re-evaluate the OP_BEGIN).',
10+
OP_DEFINE = 'Pop the top item from the stack to interpret as a function identifier (VM number between 0 and 999, inclusive). Pop the next item from the stack (the function body), and save it to the function table at the index equal to the function identifier. If that function index is out of range or already defined, error.',
11+
OP_INVOKE = 'Pop the top item from the stack to interpret as a function table index (VM number between 0 and 999, inclusive). If no function is defined at that index, error. Preserve the active bytecode at the top of the control stack, then evaluate the function body at that function table index as if it were the active bytecode (without resetting the stack, alternate stack, or evaluation limits). When the evaluation is complete, restore the original bytecode and continue evaluation after the OP_INVOKE instruction. If the bytecode is malformed, error.',
1112
}
1213

1314
/**
14-
* Descriptions for the `BCH_SPEC` instruction set.
15+
* Descriptions for the `BCH_2026_05` instruction set.
1516
*/
1617
// eslint-disable-next-line @typescript-eslint/naming-convention
1718
export const OpcodeDescriptionsBch2026 = {

src/lib/vm/instruction-sets/bch/2026/bch-2026-errors.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,10 @@ export enum AuthenticationErrorBch2026Additions {
44
unexpectedUntil = 'Encountered an OP_UNTIL that is not preceded by a matching OP_BEGIN.',
55
unexpectedUntilMissingEndIf = 'Encountered an OP_UNTIL before the previous OP_IF was closed by an OP_ENDIF.',
66
excessiveLooping = 'Program attempted an OP_UNTIL operation that would exceed the limit of repeated bytes.',
7-
malformedEval = 'Program attempted to OP_EVAL malformed bytecode.',
7+
functionIdentifierInvalid = 'Program attempted to OP_DEFINE an invalid function identifier.',
8+
functionIdentifierPreviouslyDefined = 'Program attempted to OP_DEFINE a previously-defined function identifier.',
9+
functionIdentifierUndefined = 'Program attempted to OP_INVOKE an undefined function identifier.',
10+
malformedFunction = 'Program attempted to OP_INVOKE malformed bytecode.',
811
}
912

1013
/**
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
import { binToHex } from '../../../../format/format.js';
2+
import type {
3+
AuthenticationInstructionMalformed,
4+
AuthenticationProgramStateControlStack,
5+
AuthenticationProgramStateError,
6+
AuthenticationProgramStateFunctionTable,
7+
AuthenticationProgramStateMinimum,
8+
AuthenticationProgramStateStack,
9+
} from '../../../../lib.js';
10+
import {
11+
applyError,
12+
authenticationInstructionsAreMalformed,
13+
decodeAuthenticationInstructions,
14+
disassembleAuthenticationInstructionMalformed,
15+
pushToControlStack,
16+
useOneStackItem,
17+
useOneVmNumber,
18+
} from '../../common/common.js';
19+
20+
import { ConsensusBch2026 } from './bch-2026-consensus.js';
21+
import { AuthenticationErrorBch2026 } from './bch-2026-errors.js';
22+
import { OpcodesBch2026 } from './bch-2026-opcodes.js';
23+
24+
export const createOpDefine =
25+
({
26+
maximumFunctionIdentifier = ConsensusBch2026.maximumFunctionIdentifier,
27+
minimumFunctionIdentifier = ConsensusBch2026.minimumFunctionIdentifier,
28+
} = {}) =>
29+
<
30+
State extends AuthenticationProgramStateError &
31+
AuthenticationProgramStateFunctionTable &
32+
AuthenticationProgramStateStack,
33+
>(
34+
state: State,
35+
) =>
36+
useOneVmNumber(state, (nextState, [providedInteger]) => {
37+
const functionIdentifier = Number(providedInteger);
38+
if (
39+
functionIdentifier < minimumFunctionIdentifier ||
40+
functionIdentifier > maximumFunctionIdentifier
41+
) {
42+
return applyError(
43+
nextState,
44+
AuthenticationErrorBch2026.functionIdentifierInvalid,
45+
`Function identifier (${functionIdentifier}) is outside of the valid range: ${minimumFunctionIdentifier} to ${maximumFunctionIdentifier} (inclusive).`,
46+
);
47+
}
48+
if (nextState.functionTable[functionIdentifier] !== undefined) {
49+
return applyError(
50+
nextState,
51+
AuthenticationErrorBch2026.functionIdentifierPreviouslyDefined,
52+
`Function identifier: ${functionIdentifier}. Existing contents: ${binToHex(
53+
nextState.functionTable[functionIdentifier],
54+
)}.`,
55+
);
56+
}
57+
return useOneStackItem(nextState, (finalState, [functionBody]) => {
58+
// eslint-disable-next-line functional/no-expression-statements, functional/immutable-data
59+
finalState.functionTable[functionIdentifier] = functionBody;
60+
return finalState;
61+
});
62+
});
63+
64+
export const opInvoke = <
65+
State extends AuthenticationProgramStateControlStack &
66+
AuthenticationProgramStateError &
67+
AuthenticationProgramStateFunctionTable &
68+
AuthenticationProgramStateMinimum &
69+
AuthenticationProgramStateStack,
70+
>(
71+
state: State,
72+
) =>
73+
useOneVmNumber(state, (nextState, [providedInteger]) => {
74+
const functionTableIndex = Number(providedInteger);
75+
const functionBody = nextState.functionTable[functionTableIndex];
76+
if (functionBody === undefined) {
77+
return applyError(
78+
nextState,
79+
AuthenticationErrorBch2026.functionIdentifierUndefined,
80+
`Function identifier: ${functionTableIndex}.`,
81+
);
82+
}
83+
const newInstructions = decodeAuthenticationInstructions(functionBody);
84+
if (authenticationInstructionsAreMalformed(newInstructions)) {
85+
return applyError(
86+
nextState,
87+
AuthenticationErrorBch2026.malformedFunction,
88+
`Malformed instruction: ${disassembleAuthenticationInstructionMalformed(
89+
OpcodesBch2026,
90+
newInstructions[
91+
newInstructions.length - 1
92+
] as AuthenticationInstructionMalformed,
93+
)}.`,
94+
);
95+
}
96+
const manuallyAdvance = 1;
97+
const finalState = pushToControlStack(nextState, {
98+
instructions: nextState.instructions,
99+
ip: nextState.ip + manuallyAdvance,
100+
});
101+
finalState.ip = 0 - manuallyAdvance; // eslint-disable-line functional/no-expression-statements, functional/immutable-data
102+
finalState.instructions = newInstructions; // eslint-disable-line functional/no-expression-statements, functional/immutable-data
103+
return finalState;
104+
});

src/lib/vm/instruction-sets/bch/2026/bch-2026-instruction-set.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,12 @@ import type {
1414
Sha1,
1515
Sha256,
1616
} from '../../../../lib.js';
17+
import { conditionallyEvaluate } from '../../common/common.js';
1718
import { createInstructionSetBch2025 } from '../2025/bch-2025-instruction-set.js';
1819
import { opBegin, opUntil } from '../2026/bch-2026-loops.js';
1920

2021
import { ConsensusBch2026 } from './bch-2026-consensus.js';
21-
import { opEval } from './bch-2026-eval.js';
22+
import { createOpDefine, opInvoke } from './bch-2026-functions.js';
2223
import { OpcodesBch2026 } from './bch-2026-opcodes.js';
2324
import type { AuthenticationProgramStateBch2026 } from './bch-2026-types.js';
2425
/**
@@ -100,9 +101,12 @@ export const createInstructionSetBch2026 = <
100101
/* eslint-enable functional/no-loop-statements, functional/immutable-data, functional/no-expression-statements */
101102
operations: {
102103
...instructionSet.operations,
103-
[OpcodesBch2026.OP_EVAL]: opEval,
104104
[OpcodesBch2026.OP_BEGIN]: opBegin,
105105
[OpcodesBch2026.OP_UNTIL]: opUntil,
106+
[OpcodesBch2026.OP_DEFINE]: conditionallyEvaluate(
107+
createOpDefine(consensus),
108+
),
109+
[OpcodesBch2026.OP_INVOKE]: conditionallyEvaluate(opInvoke),
106110
},
107111
};
108112
};

0 commit comments

Comments
 (0)