Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

OP_REVERSEBYTES / BCH_2020_05 #56

Merged
merged 3 commits into from
Aug 7, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 24 additions & 23 deletions .cspell.json
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
{
"$schema": "https://raw.githubusercontent.com/streetsidesoftware/cspell/master/cspell.schema.json",
"version": "0.1",
"$schema": "https://raw.githubusercontent.com/streetsidesoftware/cspell/master/cspell.schema.json",
"language": "en",
"words": [
"ANYONECANPAY",
"asmcrypto",
"auditability",
"auditable",
"bchtest",
"bchreg",
"bchtest",
"bcoin",
"bcrypto",
"bech",
Expand Down Expand Up @@ -37,19 +37,19 @@
"codepoint",
"CODESEPARATOR",
"coinbase",
"convertbits",
"combinator",
"combinators",
"convertbits",
"cyclomatic",
"deno",
"deserialize",
"deserialization",
"deserialize",
"devtools",
"DYNAMICTOP",
"ecdsa",
"elliptic's",
"emscripten",
"emscripten's",
"ecdsa",
"EQUALVERIFY",
"esnext",
"FROMALTSTACK",
Expand All @@ -58,26 +58,13 @@
"IFDUP",
"INVALIDOPCODE",
"LESSTHAN",
"LESSTHANOREQUAL",
"libauth",
"Libauth's",
"libsecp",
"lifecycle",
"locktime",
"LESSTHANOREQUAL",
"LSHIFT",
"parsimmon",
"performant",
"plusplus",
"privkey",
"preauthorize",
"preimage",
"preimages",
"prevouts",
"pubkey",
"PUBKEYS",
"PUBKEYHASH",
"PUSHBYTES",
"PUSHDATA",
"mainnet",
"malleate",
"malleated",
Expand All @@ -94,21 +81,35 @@
"NUMEQUAL",
"NUMEQUALVERIFY",
"NUMNOTEQUAL",
"parsimmon",
"performant",
"plusplus",
"preauthorize",
"preimage",
"preimages",
"prevouts",
"privkey",
"pubkey",
"PUBKEYHASH",
"PUBKEYS",
"PUSHBYTES",
"PUSHDATA",
"regtest",
"reversebytes",
"ripemd",
"RSHIFT",
"satoshi",
"satoshis",
"schnorr",
"skippable",
"seckey",
"secp",
"secp256k1",
"sighash",
"skippable",
"SMALLINTEGER",
"STACKTOP",
"STATICTOP",
"statelessly",
"STATICTOP",
"submodule",
"templating",
"testnet",
Expand All @@ -130,8 +131,8 @@
"webassembly",
"xprivkey",
"xprv",
"xpubkey",
"xpub"
"xpub",
"xpubkey"
],
"flagWords": [],
"ignorePaths": [
Expand Down
3 changes: 2 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,6 @@
"editor.formatOnSave": true,
"editor.semanticHighlighting.enabled": true,
"typescript.tsdk": "node_modules/typescript/lib",
"typescript.enablePromptUseWorkspaceTsdk": true
"typescript.enablePromptUseWorkspaceTsdk": true,
"cSpell.enabled": true
}
Original file line number Diff line number Diff line change
Expand Up @@ -592,7 +592,7 @@
"type": "object"
},
"AuthenticationVirtualMachineIdentifier": {
"description": "Allowable identifiers for authentication virtual machine versions. The `BCH`\nprefix identifies the Bitcoin Cash network, the `BSV` prefix identifies the\nBitcoin SV network, and the `BTC` prefix identifies the Bitcoin (Core)\nnetwork.",
"description": "Allowable identifiers for authentication virtual machine versions. The `BCH`\nprefix identifies the Bitcoin Cash network, the `BSV` prefix identifies the\nBitcoin SV network, and the `BTC` prefix identifies the Bitcoin (Core)\nnetwork.\n\nVirtual machine versions may be marked with the `SPEC` suffix to indicate\nthat they have not yet been deployed to a main network and are therefore only\na draft specification. After deployment, when template compatibility is\nverified, templates should update their `supported` array to indicate\ncompatibility with the live virtual machine version.",
"enum": [
"BCH_2022_11_SPEC",
"BCH_2022_11",
Expand Down
6 changes: 6 additions & 0 deletions src/lib/template/template-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,12 @@ export interface AuthenticationTemplate {
* prefix identifies the Bitcoin Cash network, the `BSV` prefix identifies the
* Bitcoin SV network, and the `BTC` prefix identifies the Bitcoin (Core)
* network.
*
* Virtual machine versions may be marked with the `SPEC` suffix to indicate
* that they have not yet been deployed to a main network and are therefore only
* a draft specification. After deployment, when template compatibility is
* verified, templates should update their `supported` array to indicate
* compatibility with the live virtual machine version.
*/
export type AuthenticationVirtualMachineIdentifier =
| 'BCH_2022_11_SPEC'
Expand Down
1 change: 1 addition & 0 deletions src/lib/vm/instruction-sets/bch/bch-descriptions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export enum OpcodeDescriptionsUniqueBCH {
OP_MOD = 'Pop the top item from the stack as a denominator (Script Number) and the next as a numerator (Script Number). Divide and push the remainder to the stack.',
OP_CHECKDATASIG = 'Pop the top 3 items from the stack. Treat the top as a public key, the second as a message, and the third as a signature. If the signature is valid, push a Script Number 1, otherwise push a Script Number 0.',
OP_CHECKDATASIGVERIFY = 'Pop the top 3 items from the stack. Treat the top as a public key, the second as a message, and the third as a signature. If the signature is not valid, error. (This operation is a combination of OP_CHECKDATASIG followed by OP_VERIFY.)',
OP_REVERSEBYTES = 'Pop the top item from the stack and reverse it, pushing the result.',
}

/**
Expand Down
67 changes: 61 additions & 6 deletions src/lib/vm/instruction-sets/bch/bch-instruction-sets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,52 +93,106 @@ const isPushOperation = (opcode: number) => opcode < OpcodesBCH.OP_16;
* transactions. Transactions which fail these rules are often called
* "non-standard" – the transactions can technically be included by miners in
* valid blocks, but most network nodes will refuse to relay them.
*
* BCH instruction sets marked `SPEC` ("specification") have not yet been
* deployed on the main network and are subject to change. After deployment, the
* `SPEC` suffix is removed. This change only effects the name of the TypeScript
* enum member – the value remains the same. E.g.
* `InstructionSetBCH.BCH_2020_05_SPEC` became `InstructionSetBCH.BCH_2020_05`,
* but the value remained `BCH_2020_05`.
*
* This allows consumers to select an upgrade policy: when a version of Libauth
* is released in which compatibility with a deployed virtual machine is
* confirmed, this change can help to identify downstream code which requires
* review.
* - Consumers which prefer to upgrade manually should specify a `SPEC` type,
* e.g. `InstructionSetBCH.BCH_2020_05_SPEC`.
* - Consumers which prefer full compatibility between Libauth version should
* specify a precise instruction set value (e.g. `BCH_2020_05`) or use the
* dedicated "current" value: `instructionSetBCHCurrentStrict`.
*/
export enum InstructionSetBCH {
BCH_2019_05 = 'BCH_2019_05',
BCH_2019_05_STRICT = 'BCH_2019_05_STRICT',
BCH_2019_11_SPEC = 'BCH_2019_11',
BCH_2019_11_STRICT_SPEC = 'BCH_2019_11_STRICT',
BCH_2019_11 = 'BCH_2019_11',
BCH_2019_11_STRICT = 'BCH_2019_11_STRICT',
BCH_2020_05 = 'BCH_2020_05',
BCH_2020_05_STRICT = 'BCH_2020_05_STRICT',
BCH_2020_11_SPEC = 'BCH_2020_11',
BCH_2020_11_STRICT_SPEC = 'BCH_2020_11_STRICT',
BCH_2021_05_SPEC = 'BCH_2021_05',
BCH_2021_05_STRICT_SPEC = 'BCH_2021_05_STRICT',
BCH_2021_11_SPEC = 'BCH_2021_11',
BCH_2021_11_STRICT_SPEC = 'BCH_2021_11_STRICT',
BCH_2022_05_SPEC = 'BCH_2022_05',
BCH_2022_05_STRICT_SPEC = 'BCH_2022_05_STRICT',
BCH_2022_11_SPEC = 'BCH_2022_11',
BCH_2022_11_STRICT_SPEC = 'BCH_2022_11_STRICT',
}

/**
* The current strict virtual machine version used by the Bitcoin Cash (BCH)
* network.
*/
export const instructionSetBCHCurrentStrict =
InstructionSetBCH.BCH_2019_05_STRICT;
InstructionSetBCH.BCH_2020_05_STRICT;

// eslint-disable-next-line complexity
export const getFlagsForInstructionSetBCH = (
instructionSet: InstructionSetBCH
) => {
switch (instructionSet) {
case InstructionSetBCH.BCH_2019_05:
return {
disallowUpgradableNops: false,
opReverseBytes: false,
requireBugValueZero: false,
requireMinimalEncoding: false,
requireNullSignatureFailures: true,
};
case InstructionSetBCH.BCH_2019_05_STRICT:
return {
disallowUpgradableNops: true,
opReverseBytes: false,
requireBugValueZero: false,
requireMinimalEncoding: true,
requireNullSignatureFailures: true,
};
case InstructionSetBCH.BCH_2019_11_SPEC:
case InstructionSetBCH.BCH_2019_11:
return {
disallowUpgradableNops: false,
opReverseBytes: false,
requireBugValueZero: true,
requireMinimalEncoding: true,
requireNullSignatureFailures: true,
};
case InstructionSetBCH.BCH_2019_11_STRICT_SPEC:
case InstructionSetBCH.BCH_2019_11_STRICT:
return {
disallowUpgradableNops: true,
opReverseBytes: false,
requireBugValueZero: true,
requireMinimalEncoding: true,
requireNullSignatureFailures: true,
};
case InstructionSetBCH.BCH_2020_05:
return {
disallowUpgradableNops: false,
opReverseBytes: true,
requireBugValueZero: false,
requireMinimalEncoding: false,
requireNullSignatureFailures: true,
};
case InstructionSetBCH.BCH_2020_05_STRICT:
return {
disallowUpgradableNops: true,
opReverseBytes: true,
requireBugValueZero: true,
requireMinimalEncoding: true,
requireNullSignatureFailures: true,
};
default:
return new Error(
`${instructionSet as string} is not an instruction set.`
`${instructionSet as string} is not a known instruction set.`
) as never;
}
};
Expand All @@ -162,6 +216,7 @@ export const createInstructionSetBCH = ({
}: {
flags: {
readonly disallowUpgradableNops: boolean;
readonly opReverseBytes: boolean;
readonly requireBugValueZero: boolean;
readonly requireMinimalEncoding: boolean;
readonly requireNullSignatureFailures: boolean;
Expand Down
9 changes: 6 additions & 3 deletions src/lib/vm/instruction-sets/bch/bch-opcodes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -205,10 +205,13 @@ export enum OpcodesBCH {
* Previously `OP_UNKNOWN187`
*/
OP_CHECKDATASIGVERIFY = 0xbb,
/**
* Previously `OP_UNKNOWN188`
*/
OP_REVERSEBYTES = 0xbc,
/**
* A.K.A. `FIRST_UNDEFINED_OP_VALUE`
*/
OP_UNKNOWN188 = 0xbc,
OP_UNKNOWN189 = 0xbd,
OP_UNKNOWN190 = 0xbe,
OP_UNKNOWN191 = 0xbf,
Expand Down Expand Up @@ -314,9 +317,9 @@ export enum OpcodeAlternateNamesBCH {
*/
OP_UNKNOWN187 = 0xbb,
/**
* A.K.A. `OP_UNKNOWN188`
* A.K.A. `OP_UNKNOWN189`
*/
FIRST_UNDEFINED_OP_VALUE = 0xbc,
FIRST_UNDEFINED_OP_VALUE = 0xbd,
/**
* A.K.A. `OP_UNKNOWN240`. Some implementations have reserved opcodes
* `0xf0` through `0xf7` for a future range of multi-byte opcodes, though none
Expand Down
53 changes: 34 additions & 19 deletions src/lib/vm/instruction-sets/bch/bch-operations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,13 @@ export const opCheckDataSigVerify = <
opVerify<State, Errors>()
);

export const opReverseBytes = <
State extends AuthenticationProgramStateStack
>() => (state: State) =>
useOneStackItem(state, (nextState, [item]) =>
pushToStack(nextState, item.reverse())
);

export const bitcoinCashOperations = <
Opcodes,
State extends AuthenticationProgramStateCommon<
Expand All @@ -327,26 +334,34 @@ export const bitcoinCashOperations = <
verifySignatureDERLowS: Secp256k1['verifySignatureDERLowS'];
};
flags: {
opReverseBytes: boolean;
requireBugValueZero: boolean;
requireMinimalEncoding: boolean;
requireNullSignatureFailures: boolean;
};
}) => ({
[OpcodesBCH.OP_CAT]: opCat<State>(),
[OpcodesBCH.OP_SPLIT]: opSplit<State>(flags),
[OpcodesBCH.OP_NUM2BIN]: opNum2Bin<State>(),
[OpcodesBCH.OP_BIN2NUM]: opBin2Num<State>(),
[OpcodesBCH.OP_AND]: opAnd<State>(),
[OpcodesBCH.OP_OR]: opOr<State>(),
[OpcodesBCH.OP_XOR]: opXor<State>(),
[OpcodesBCH.OP_DIV]: opDiv<State>(flags),
[OpcodesBCH.OP_MOD]: opMod<State>(flags),
[OpcodesBCH.OP_CHECKDATASIG]: opCheckDataSig<State, AuthenticationErrorBCH>({
secp256k1,
sha256,
}),
[OpcodesBCH.OP_CHECKDATASIGVERIFY]: opCheckDataSigVerify<
State,
AuthenticationErrorBCH
>({ secp256k1, sha256 }),
});
}) => {
const operations = {
[OpcodesBCH.OP_CAT]: opCat<State>(),
[OpcodesBCH.OP_SPLIT]: opSplit<State>(flags),
[OpcodesBCH.OP_NUM2BIN]: opNum2Bin<State>(),
[OpcodesBCH.OP_BIN2NUM]: opBin2Num<State>(),
[OpcodesBCH.OP_AND]: opAnd<State>(),
[OpcodesBCH.OP_OR]: opOr<State>(),
[OpcodesBCH.OP_XOR]: opXor<State>(),
[OpcodesBCH.OP_DIV]: opDiv<State>(flags),
[OpcodesBCH.OP_MOD]: opMod<State>(flags),
[OpcodesBCH.OP_CHECKDATASIG]: opCheckDataSig<State, AuthenticationErrorBCH>(
{
secp256k1,
sha256,
}
),
[OpcodesBCH.OP_CHECKDATASIGVERIFY]: opCheckDataSigVerify<
State,
AuthenticationErrorBCH
>({ secp256k1, sha256 }),
};
return flags.opReverseBytes
? { ...operations, [OpcodesBCH.OP_REVERSEBYTES]: opReverseBytes<State>() }
: operations;
};
4 changes: 2 additions & 2 deletions src/lib/vm/instruction-sets/bch/bch.script-tests.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,9 +98,9 @@ const pendingTests = tests;
const elide = (text: string, length: number) =>
text.length > length ? `${text.slice(0, length)}...` : text;

const vmPromise = instantiateVirtualMachineBCH(InstructionSetBCH.BCH_2019_05);
const vmPromise = instantiateVirtualMachineBCH(InstructionSetBCH.BCH_2020_05);
const vmStrictPromise = instantiateVirtualMachineBCH(
InstructionSetBCH.BCH_2019_05_STRICT
InstructionSetBCH.BCH_2020_05_STRICT
);
const sha256Promise = instantiateSha256();

Expand Down
Loading