edge-currency-plugins 3.14.0 → 3.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -45,9 +45,9 @@ var _types5 = require('../keymanager/types');
45
45
  const asUtxoSignMessageOtherParams = _cleaners.asObject.call(void 0, {
46
46
  publicAddress: _cleaners.asString,
47
47
  // Defaults to the legacy Electrum encoding so existing callers keep the
48
- // format they already produce. BIP-137 is opt-in, since emitting a BIP-137
49
- // header to a verifier expecting the legacy one is just as broken as the
50
- // reverse.
48
+ // format they already produce. BIP-137 and BIP-322 are opt-in, since
49
+ // emitting either to a verifier expecting the legacy encoding is just as
50
+ // broken as the reverse.
51
51
  signatureFormat: _cleaners.asMaybe.call(void 0, _types5.asUtxoSignatureFormat, 'electrum')
52
52
  }); exports.asUtxoSignMessageOtherParams = asUtxoSignMessageOtherParams
53
53
 
@@ -8,6 +8,7 @@
8
8
 
9
9
 
10
10
  var _altcoinjs = require('altcoin-js');
11
+ var _psbtutils = require('altcoin-js/src/psbt/psbtutils');
11
12
  var _biggystring = require('biggystring');
12
13
  var _bip32 = require('bip32'); var bip32 = _interopRequireWildcard(_bip32);
13
14
  var _bip39 = require('bip39'); var bip39 = _interopRequireWildcard(_bip39);
@@ -967,6 +968,75 @@ function getBip137SegwitType(
967
968
  }
968
969
  }
969
970
 
971
+ /**
972
+ * The BIP-322 message hash: a BIP-340 style tagged hash of the raw message
973
+ * bytes. Unlike the legacy format there is no coin-specific prefix.
974
+ */
975
+ function bip322MessageHash(message) {
976
+ const tagHash = _altcoinjs.crypto.sha256(Buffer.from('BIP0322-signed-message', 'utf8'))
977
+ return _altcoinjs.crypto.sha256(
978
+ Buffer.concat([tagHash, tagHash, Buffer.from(message, 'utf8')])
979
+ )
980
+ } exports.bip322MessageHash = bip322MessageHash;
981
+
982
+ /**
983
+ * Signs `message` per BIP-322 and returns the witness stack that spends the
984
+ * virtual `to_spend` output locked to the key's address. Native SegWit
985
+ * (bip84) and nested SegWit (bip49) both spend through a P2WPKH witness; a
986
+ * nested address' redeem script is implied by the key, so verifiers rebuild
987
+ * the scriptSig from the witness. Returns `undefined` for legacy formats,
988
+ * which have no witness.
989
+ */
990
+ function signBip322Witness(
991
+ message,
992
+ keyPair,
993
+ format
994
+ ) {
995
+ if (format !== 'bip84' && format !== 'bip49') return undefined
996
+
997
+ const p2wpkh = _altcoinjs.payments.p2wpkh({ pubkey: keyPair.publicKey })
998
+ const scriptPubkey =
999
+ format === 'bip84'
1000
+ ? p2wpkh.output
1001
+ : _altcoinjs.payments.p2sh({ redeem: p2wpkh }).output
1002
+ // BIP-143 signs a P2WPKH input against the P2PKH script of its key hash.
1003
+ const scriptCode = _altcoinjs.payments.p2pkh({ hash: p2wpkh.hash }).output
1004
+ if (scriptPubkey == null || scriptCode == null) {
1005
+ throw new Error('Address could not sign message')
1006
+ }
1007
+
1008
+ const toSpend = new (0, _altcoinjs.Transaction)()
1009
+ toSpend.version = 0
1010
+ toSpend.locktime = 0
1011
+ toSpend.addInput(
1012
+ Buffer.alloc(32),
1013
+ 0xffffffff,
1014
+ 0,
1015
+ _altcoinjs.script.compile([_altcoinjs.opcodes.OP_0, bip322MessageHash(message)])
1016
+ )
1017
+ toSpend.addOutput(scriptPubkey, 0)
1018
+
1019
+ const toSign = new (0, _altcoinjs.Transaction)()
1020
+ toSign.version = 0
1021
+ toSign.locktime = 0
1022
+ toSign.addInput(toSpend.getHash(), 0, 0)
1023
+ toSign.addOutput(_altcoinjs.script.compile([_altcoinjs.opcodes.OP_RETURN]), 0)
1024
+
1025
+ const sighash = toSign.hashForWitnessV0(
1026
+ 0,
1027
+ scriptCode,
1028
+ 0,
1029
+ _altcoinjs.Transaction.SIGHASH_ALL
1030
+ )
1031
+ // Low-R grinding matches Bitcoin Core, so the output is byte-identical to
1032
+ // the signatures its `signmessage` and the BIP-322 test vectors produce.
1033
+ const signature = _altcoinjs.script.signature.encode(
1034
+ keyPair.sign(sighash, true),
1035
+ _altcoinjs.Transaction.SIGHASH_ALL
1036
+ )
1037
+ return [signature, keyPair.publicKey]
1038
+ }
1039
+
970
1040
  function signMessageBase64(
971
1041
  message,
972
1042
  privateKey,
@@ -979,6 +1049,14 @@ function getBip137SegwitType(
979
1049
  if (keyPair.privateKey == null) {
980
1050
  throw new Error('Address could not sign message')
981
1051
  }
1052
+ if (signatureFormat === 'bip322') {
1053
+ const witness = signBip322Witness(message, keyPair, format)
1054
+ // Legacy P2PKH addresses have no witness to sign with. BIP-322 has them
1055
+ // fall back to the legacy message format, which the Electrum encoding
1056
+ // below produces.
1057
+ if (witness != null)
1058
+ return _psbtutils.witnessStackToScriptWitness.call(void 0, witness).toString('base64')
1059
+ }
982
1060
  // BIP137 encodes the address type in the signature's header byte. Native
983
1061
  // SegWit (bip84 / P2WPKH) and nested SegWit (bip49 / P2SH-P2WPKH) each have
984
1062
  // their own header range; verifiers such as Bringin reject a SegWit address
@@ -8,8 +8,12 @@ var _types = require('edge-core-js/types');
8
8
  * about the script type.
9
9
  * - `bip137`: additionally encodes the signing address' script type, which
10
10
  * verifiers such as Bringin require for SegWit addresses.
11
+ * - `bip322`: a BIP-322 "simple" signature (the consensus-encoded witness
12
+ * of a virtual transaction spending from the address) for SegWit
13
+ * addresses. Legacy P2PKH addresses have no simple form, so BIP-322 has
14
+ * them sign in the legacy format, which is the `electrum` encoding.
11
15
  */
12
- const asUtxoSignatureFormat = _cleaners.asValue.call(void 0, 'electrum', 'bip137'); exports.asUtxoSignatureFormat = asUtxoSignatureFormat
16
+ const asUtxoSignatureFormat = _cleaners.asValue.call(void 0, 'electrum', 'bip137', 'bip322'); exports.asUtxoSignatureFormat = asUtxoSignatureFormat
13
17
 
14
18
 
15
19
 
@@ -23,7 +23,7 @@ export interface UtxoTxOtherParams {
23
23
  export declare type UtxoSignMessageOtherParams = ReturnType<typeof asUtxoSignMessageOtherParams>;
24
24
  export declare const asUtxoSignMessageOtherParams: import("cleaners").ObjectCleaner<{
25
25
  publicAddress: string;
26
- signatureFormat: "electrum" | "bip137";
26
+ signatureFormat: "electrum" | "bip137" | "bip322";
27
27
  }>;
28
28
  export declare type UtxoSpendInfoOtherParams = ReturnType<typeof asUtxoSpendInfoOtherParams>;
29
29
  export declare const asUtxoSpendInfoOtherParams: import("cleaners").ObjectCleaner<{
@@ -1,3 +1,4 @@
1
+ /// <reference types="node" />
1
2
  import { EdgeLog, EdgeMemo } from 'edge-core-js/types';
2
3
  import { ChangePath, CurrencyFormat, FeeInfo } from '../../plugin/types';
3
4
  import { UtxoData } from '../db/types';
@@ -203,6 +204,11 @@ export declare const xprivToPrivateKey: (args: XPrivToPrivateKeyArgs) => string;
203
204
  export declare function privateKeyToWIF(args: PrivateKeyToWIFArgs): string;
204
205
  export declare const wifToPrivateKeyEncoding: (args: WIFToPrivateKeyEncodingArgs) => PrivateKeyEncoding;
205
206
  export declare function privateKeyEncodingToPubkey(privateKeyEncoding: PrivateKeyEncoding): string;
207
+ /**
208
+ * The BIP-322 message hash: a BIP-340 style tagged hash of the raw message
209
+ * bytes. Unlike the legacy format there is no coin-specific prefix.
210
+ */
211
+ export declare function bip322MessageHash(message: string): Buffer;
206
212
  export declare function signMessageBase64(message: string, privateKey: string, format: CurrencyFormat, coin: string, signatureFormat?: UtxoSignatureFormat): string;
207
213
  export declare function makeTx(args: MakeTxArgs): MakeTxReturn;
208
214
  export declare function signTx(args: SignTxArgs): Promise<SignTxReturn>;
@@ -7,8 +7,12 @@ import { EdgeTokenId, InsufficientFundsError } from 'edge-core-js/types';
7
7
  * about the script type.
8
8
  * - `bip137`: additionally encodes the signing address' script type, which
9
9
  * verifiers such as Bringin require for SegWit addresses.
10
+ * - `bip322`: a BIP-322 "simple" signature (the consensus-encoded witness
11
+ * of a virtual transaction spending from the address) for SegWit
12
+ * addresses. Legacy P2PKH addresses have no simple form, so BIP-322 has
13
+ * them sign in the legacy format, which is the `electrum` encoding.
10
14
  */
11
- export declare const asUtxoSignatureFormat: Cleaner<"electrum" | "bip137">;
15
+ export declare const asUtxoSignatureFormat: Cleaner<"electrum" | "bip137" | "bip322">;
12
16
  export declare type UtxoSignatureFormat = ReturnType<typeof asUtxoSignatureFormat>;
13
17
  interface InsufficientFundsErrorOptsPlus {
14
18
  tokenId: EdgeTokenId;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "edge-currency-plugins",
3
- "version": "3.14.0",
3
+ "version": "3.15.0",
4
4
  "description": "Edge currency plugins to fetch and process wallet accounts, balances and transactions.",
5
5
  "homepage": "https://edge.app/",
6
6
  "repository": "https://github.com/EdgeApp/edge-currency-plugins",