Skip to content
Draft
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
3 changes: 3 additions & 0 deletions website/docs/language/functions.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,8 @@ bool checkSig(sig s, pubkey pk)

Checks that transaction signature `s` is valid for the current transaction and matches with public key `pk`.

A signature always authorizes the spending of a single input, but the signer chooses how much of the surrounding transaction that authorization is bound to. This is controlled by the [sighash flag][hashtype], encoded in the last byte of `s`. It defaults to `SIGHASH_ALL`, which binds the signature to all of the transaction's inputs and outputs, so the signed input can only be spent in exactly that transaction. Other flags leave parts of the transaction context uncommitted. See the [HashType][hashtype] documentation for the available flags and how to restrict which ones your contract accepts.

### checkMultiSig()
```solidity
bool checkMultiSig(sig[] sigs, pubkey[] pks)
Expand Down Expand Up @@ -129,3 +131,4 @@ Using `bytes20 placeholderPkh = toPaddedBytes(0, 20)` will generate a 20 byte ze

[bip146]: https://github.com/bitcoin/bips/blob/master/bip-0146.mediawiki
[local-state-guide]: /docs/guides/covenants#keeping-local-state-in-nfts
[hashtype]: /docs/sdk/signature-templates#hashtype
2 changes: 1 addition & 1 deletion website/docs/language/types.md
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ Operators:
- `!=` (inequality)

### Transaction Signature
`sig`: Byte sequence representing a transaction signature. Generally 65 bytes long.
`sig`: Byte sequence representing a transaction signature. Generally 65 bytes long: a 64-byte Schnorr signature followed by a single sighash flag byte that indicates which parts of the transaction were signed. See [HashType](/docs/sdk/signature-templates#hashtype) for the meaning of this byte.

Operators:

Expand Down
23 changes: 22 additions & 1 deletion website/docs/sdk/signature-templates.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,9 @@ const signature = aliceTemplate.signMessageHash(sha256(hexToBin('000000000000000

### HashType

The default `hashtype` is `HashType.SIGHASH_ALL | HashType.SIGHASH_UTXOS` because this is the most secure option for smart contract use cases.
The `hashtype` (also called the sighash flag) determines which parts of the spending transaction the signature commits to. When the transaction is signed, these parts are serialized into a signing serialization (or sighash preimage), which is hashed and signed.

The default `hashtype` is `HashType.SIGHASH_ALL | HashType.SIGHASH_UTXOS` because this is the most secure option for smart contract use cases: it commits to every input and output of the transaction, so the signed transaction cannot be altered in any way after signing.

```ts
export enum HashType {
Expand All @@ -105,6 +107,20 @@ export enum HashType {
}
```

`SIGHASH_ALL`, `SIGHASH_NONE` and `SIGHASH_SINGLE` choose which outputs are signed, while `SIGHASH_UTXOS` and `SIGHASH_ANYONECANPAY` are modifiers that can be OR'd on top to change what else is committed to.

| Flag | Value | Commits to | Typical use |
| --- | --- | --- | --- |
| `SIGHASH_ALL` | `0x01` | all inputs and **all** outputs | the default — sign the exact transaction |
| `SIGHASH_NONE` | `0x02` | all inputs, but **no** outputs | let the outputs be decided after signing |
| `SIGHASH_SINGLE` | `0x03` | all inputs, and only the **one** output at the same index as the signed input | pair a single input to a single output |
| `SIGHASH_UTXOS` | `0x20` | *(modifier)* additionally commits to the full contents of the UTXOs being spent | recommended for all contracts — see below |
| `SIGHASH_ANYONECANPAY` | `0x80` | *(modifier)* only the **current** input, allowing other inputs to be added | crowdfunding-style transactions where anyone can add an input |

The default `SIGHASH_ALL | SIGHASH_UTXOS` is the right choice for almost all smart contract use cases: `SIGHASH_UTXOS` commits to the full value and token contents of every UTXO being spent, which protects introspection-based covenants against an attacker substituting a spent UTXO for a different one of equal amount. The other flags weaken these commitments. `SIGHASH_NONE` and `SIGHASH_SINGLE` leave outputs unsigned, making the transaction malleable, and `SIGHASH_ANYONECANPAY` only signs the current input. Only use them when you specifically need that flexibility.

For a full technical breakdown of the signing serialization and every valid flag combination, see the [Bitcoin Cash transaction signing reference][tx-signing].

#### Example
```ts
const wif = 'L4vmKsStbQaCvaKPnCzdRArZgdAxTqVx8vjMGLW5nHtWdRguiRi1';
Expand All @@ -116,6 +132,10 @@ const signatureTemplate = new SignatureTemplate(
const configuredHashType = signatureTemplate.getHashType()
```

#### The hashtype byte

The `hashtype` is appended as a single byte to the end of every signature, so a validator or contract can tell how a signature was produced by inspecting its last byte. On Bitcoin Cash the `SIGHASH_FORKID` bit (`0x40`) is always set. `SignatureTemplate` OR's it in automatically, so the byte appended to the signature is your `hashtype` combined with `0x40`. For example the default `SIGHASH_ALL | SIGHASH_UTXOS` (`0x21`) is appended as `0x61`. This is the value to compare against when inspecting a signature's last byte inside a contract.

### SignatureAlgorithm

The `signatureAlgorithm` parameter determines the cryptographic algorithm used for signing. By default, the modern and compact Schnorr algorithm is used.
Expand All @@ -141,3 +161,4 @@ const configuredSignatureAlgorithm = signatureTemplate.getSignatureAlgorithm()
[wif]: https://en.bitcoin.it/wiki/Wallet_import_format
[ecpair]: https://bchjs.fullstack.cash/#api-ECPair
[privatekey]: https://github.com/bitpay/bitcore/blob/master/packages/bitcore-lib-cash/docs/privatekey.md
[tx-signing]: https://documentation.cash/protocol/blockchain/transaction/transaction-signing.html
Loading