mainnet-js 2.2.4 → 2.2.6

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,6 +45,18 @@ describe("Test message Signing and Verification", () => {
45
45
  "gE9BDBFAOqW+yoOzABjnM+LQRWHd4dvUVrsTR+sIWsU="
46
46
  );
47
47
  expect(result.details!.publicKeyHashMatch).toBe(true);
48
+ expect(result.details!.publicKeyMatch).toBe(false);
49
+ expect(result.details!.signatureValid).toBe(true);
50
+ expect(result.details!.signatureType).toBe("recoverable");
51
+
52
+ let msg2 = "Lessons for China from Japan’s lost decade";
53
+ result = await SignedMessage.verify(msg2, sig.signature, w1.cashaddr!);
54
+ expect(result.valid).toBe(false);
55
+ expect(result.details!.messageHash).toBe(
56
+ "070kQIcYPSHApGdOGH0O81N1AkMbNKwCTM3IX2Svd3I="
57
+ );
58
+ expect(result.details!.publicKeyHashMatch).toBe(false);
59
+ expect(result.details!.publicKeyMatch).toBe(false);
48
60
  expect(result.details!.signatureValid).toBe(true);
49
61
  expect(result.details!.signatureType).toBe("recoverable");
50
62
  });
@@ -64,6 +76,9 @@ describe("Test message Signing and Verification", () => {
64
76
  let sig = await SignedMessage.sign(msg, w.privateKey!);
65
77
  let result = await SignedMessage.verify(msg, sig.signature, w.cashaddr!);
66
78
  expect(result.valid).toBe(true);
79
+
80
+ result = await SignedMessage.verify("test2", sig.signature, w.cashaddr!);
81
+ expect(result.valid).toBe(false);
67
82
  });
68
83
 
69
84
  test("Test signing and verifying regtest signature using Alice's wallet", async () => {
@@ -75,6 +90,9 @@ describe("Test message Signing and Verification", () => {
75
90
 
76
91
  let result = await SignedMessage.verify(msg, sig.signature, w.cashaddr!);
77
92
  expect(result.valid).toBe(true);
93
+
94
+ result = await SignedMessage.verify("test2", sig.signature, w.cashaddr!);
95
+ expect(result.valid).toBe(false);
78
96
  });
79
97
 
80
98
  test("Test signing and verifying regtest signature using Alice's wallet", async () => {
@@ -85,6 +103,9 @@ describe("Test message Signing and Verification", () => {
85
103
  let sig = await SignedMessage.sign(msg, w.privateKey!);
86
104
  let result = await SignedMessage.verify(msg, sig.signature, w.cashaddr!);
87
105
  expect(result.valid).toBe(true);
106
+
107
+ result = await SignedMessage.verify("测试二", sig.signature, w.cashaddr!);
108
+ expect(result.valid).toBe(false);
88
109
  });
89
110
 
90
111
  test("Test signing and verifying a schnorr signature", async () => {
@@ -101,6 +122,16 @@ describe("Test message Signing and Verification", () => {
101
122
  );
102
123
  expect(result.valid).toBe(true);
103
124
  expect(result.details!.signatureType).toBe("schnorr");
125
+
126
+ let msg2 =
127
+ "Biggest Selloff in 25 Years Hits Japan Bonds as BOJ Loosens Grip";
128
+ let invalid = await SignedMessage.verify(
129
+ msg2,
130
+ sig.raw!.schnorr,
131
+ undefined,
132
+ w.publicKey!
133
+ );
134
+ expect(invalid.valid).toBe(false);
104
135
  });
105
136
 
106
137
  test("Test signing and verifying a der signature", async () => {
@@ -133,6 +164,16 @@ describe("Test message Signing and Verification", () => {
133
164
  );
134
165
  expect(result.valid).toBe(true);
135
166
  expect(result.details!.signatureType).toBe("ecdsa");
167
+
168
+ let msg2 =
169
+ "Biggest Selloff in 25 Years Hits Japan Bonds as BOJ Loosens Grip";
170
+ let invalid = await SignedMessage.verify(
171
+ msg2,
172
+ sig.raw!.ecdsa,
173
+ undefined,
174
+ w.publicKey!
175
+ );
176
+ expect(invalid.valid).toBe(false);
136
177
  });
137
178
 
138
179
  test("Test signing and verifying a long message", async () => {
@@ -160,10 +201,20 @@ describe("Test message Signing and Verification", () => {
160
201
  w1.cashaddr!
161
202
  );
162
203
  expect(result.valid).toBe(true);
204
+
205
+ let msg2 =
206
+ "Biggest Selloff in 25 Years Hits Japan Bonds as BOJ Loosens Grip";
207
+ let invalid = await Wallet.signedMessage.verify(
208
+ msg2,
209
+ sig.signature,
210
+ w1.cashaddr!
211
+ );
212
+ expect(invalid.valid).toBe(false);
163
213
  });
164
214
 
165
215
  test("Test electron cash example from a wallet instance", async () => {
166
216
  let msg1 = "Chancellor on brink of second bailout for banks";
217
+
167
218
  let w1 = await Wallet.fromId(
168
219
  `wif:mainnet:L1TnU2zbNaAqMoVh65Cyvmcjzbrj41Gs9iTLcWbpJCMynXuap6UN`
169
220
  );
@@ -173,5 +224,40 @@ describe("Test message Signing and Verification", () => {
173
224
  let sig = await w1.sign(msg1);
174
225
  let result = await w1.verify(msg1, sig.signature);
175
226
  expect(result.valid).toBe(true);
227
+
228
+ let msg2 =
229
+ "Biggest Selloff in 25 Years Hits Japan Bonds as BOJ Loosens Grip";
230
+ let invalid = await w1.verify(msg2, sig.signature);
231
+ expect(invalid.valid).toBe(false);
232
+ });
233
+
234
+ test("Test electron cash example from a wallet instance", async () => {
235
+ let beak = "Eeny meeny, hide & seek―catch a cephalopod by the beak";
236
+ let beakSig =
237
+ "H2a0aK6ZhF5rii4yzKkE+15yLTaQPa4KzoGXwYNHm5I+OYxRdcpTiUVZm3h6+ocy2JYxb0UUrQn7UWh8IcxzEtk=";
238
+
239
+ let falseMessage = "Employer provided healthcare is a benefit.";
240
+
241
+ let w1 = await Wallet.fromId(
242
+ `watch:mainnet:qqad5sy4jml3f6vcp246dulsex04xp48wq23d35rqe`
243
+ );
244
+ expect(w1.cashaddr!).toBe(
245
+ "bitcoincash:qqad5sy4jml3f6vcp246dulsex04xp48wq23d35rqe"
246
+ );
247
+ let result = await w1.verify(beak, beakSig);
248
+ expect(result.valid).toBe(true);
249
+ expect(result.details?.publicKeyHashMatch).toBe(true);
250
+ expect(result.details?.publicKeyMatch).toBe(false);
251
+ expect(result.details?.signatureValid).toBe(true);
252
+ expect(result.details?.signatureType).toBe("recoverable");
253
+
254
+ let badResult = await w1.verify(falseMessage, beakSig);
255
+ expect(badResult.valid).toBe(false);
256
+
257
+ // While the recoverable sig is valid, it doesn't match the message.
258
+ expect(badResult.details?.signatureValid).toBe(true);
259
+ expect(badResult.details?.publicKeyHashMatch).toBe(false);
260
+ expect(badResult.details?.publicKeyMatch).toBe(false);
261
+ expect(result.details?.signatureType).toBe("recoverable");
176
262
  });
177
263
  });
@@ -125,7 +125,8 @@ export class SignedMessage implements SignedMessageI {
125
125
  let messageHash = await hash_message(message);
126
126
  let sig = base64ToBin(signature);
127
127
 
128
- let valid = false;
128
+ let signatureValid = false;
129
+ let keyMatch = false;
129
130
  let pkhMatch = false;
130
131
  let pkh, signatureType;
131
132
 
@@ -143,7 +144,7 @@ export class SignedMessage implements SignedMessageI {
143
144
 
144
145
  pkh = await hash160(recoveredPk);
145
146
  signatureType = "recoverable";
146
- valid = secp256k1.verifySignatureCompact(
147
+ signatureValid = secp256k1.verifySignatureCompact(
147
148
  rawSig,
148
149
  recoveredPk,
149
150
  messageHash
@@ -163,29 +164,33 @@ export class SignedMessage implements SignedMessageI {
163
164
  } else if (publicKey) {
164
165
  if (secp256k1.verifySignatureDER(sig, publicKey, messageHash)) {
165
166
  signatureType = "der";
166
- valid = true;
167
+ signatureValid = true;
168
+ keyMatch = true;
167
169
  } else if (
168
170
  secp256k1.verifySignatureSchnorr(sig, publicKey, messageHash)
169
171
  ) {
170
172
  signatureType = "schnorr";
171
- valid = true;
173
+ signatureValid = true;
174
+ keyMatch = true;
172
175
  } else if (
173
176
  secp256k1.verifySignatureCompact(sig, publicKey, messageHash)
174
177
  ) {
175
178
  signatureType = "ecdsa";
176
- valid = true;
179
+ signatureValid = true;
180
+ keyMatch = true;
177
181
  } else {
178
182
  signatureType = "na";
179
183
  }
180
184
  }
181
185
 
182
186
  return {
183
- valid: valid,
187
+ valid: signatureValid && (keyMatch || pkhMatch),
184
188
  details: {
185
- signatureValid: valid,
189
+ signatureValid: signatureValid,
186
190
  signatureType: signatureType,
187
191
  messageHash: binToBase64(messageHash),
188
192
  publicKeyHashMatch: pkhMatch,
193
+ publicKeyMatch: keyMatch,
189
194
  },
190
195
  };
191
196
  }
package/src/wallet/Wif.ts CHANGED
@@ -1,13 +1,21 @@
1
1
  //#region Imports
2
2
  // Stable
3
- import { encodeHdPublicKey, HdKeyNetwork, secp256k1 } from "@bitauth/libauth";
3
+ import {
4
+ decodeCashAddress,
5
+ decodeCashAddressVersionByte,
6
+ encodeHdPublicKey,
7
+ HdKeyNetwork,
8
+ secp256k1,
9
+ } from "@bitauth/libauth";
4
10
 
5
11
  // Unstable?
6
12
  import {
7
13
  binToHex,
8
14
  CashAddressNetworkPrefix,
15
+ CashAddressType,
9
16
  deriveHdPublicNode,
10
17
  decodePrivateKeyWif,
18
+ encodeCashAddress,
11
19
  encodePrivateKeyWif,
12
20
  deriveHdPrivateNodeFromSeed,
13
21
  deriveHdPath,
@@ -497,10 +505,29 @@ export class Wallet extends BaseWallet {
497
505
  }
498
506
  }
499
507
 
500
- this.cashaddr = `${addressPrefix}:${addressBase}`;
508
+ const prefixedAddress = `${addressPrefix}:${addressBase}`;
509
+
510
+ // check if a token aware address was provided
511
+ let addressData = decodeCashAddress(prefixedAddress);
512
+ if (typeof addressData === "string") throw addressData;
513
+
514
+ this.publicKeyHash = addressData.payload;
515
+
516
+ let nonTokenAwareType = addressData.type;
517
+ if (nonTokenAwareType == CashAddressType.p2pkhWithTokens)
518
+ nonTokenAwareType = CashAddressType.p2pkh;
519
+ if (nonTokenAwareType == CashAddressType.p2shWithTokens)
520
+ nonTokenAwareType = CashAddressType.p2sh;
521
+ if (nonTokenAwareType == CashAddressType.p2pkh)
522
+ this.publicKeyHash = addressData.payload;
523
+
524
+ this.cashaddr = encodeCashAddress(
525
+ addressData.prefix as CashAddressNetworkPrefix,
526
+ nonTokenAwareType,
527
+ addressData.payload
528
+ );
501
529
  this.address = this.cashaddr;
502
- this.publicKeyHash = derivePublicKeyHash(this.cashaddr);
503
- this.tokenaddr = deriveTokenaddr(this.publicKeyHash, this.networkPrefix);
530
+ this.tokenaddr = deriveTokenaddr(addressData.payload, this.networkPrefix);
504
531
 
505
532
  return this;
506
533
  }
@@ -0,0 +1,58 @@
1
+ import { RegTestWallet, TestNetWallet, Wallet } from "./Wif";
2
+ import { initProviders, disconnectProviders } from "../network/Connection";
3
+
4
+ beforeAll(async () => {
5
+ await initProviders();
6
+ });
7
+ afterAll(async () => {
8
+ await disconnectProviders();
9
+ });
10
+
11
+ describe(`Test creation of wallet from walletId`, () => {
12
+ test("Get a regtest wallet from string id", async () => {
13
+ const ADDRESS = "bchreg:qpttdv3qg2usm4nm7talhxhl05mlhms3ys43u76rn0";
14
+ const ADDRESS_TOKEN = "bchreg:zpttdv3qg2usm4nm7talhxhl05mlhms3ysjm0q59vu";
15
+
16
+ let w = await RegTestWallet.fromId(
17
+ "wif:regtest:cNfsPtqN2bMRS7vH5qd8tR8GMvgXyL5BjnGAKgZ8DYEiCrCCQcP6"
18
+ );
19
+
20
+ expect(w.cashaddr!.startsWith("bchreg:")).toBeTruthy();
21
+ expect(w.address!).toBe(ADDRESS);
22
+ expect(w.cashaddr!).toBe(ADDRESS);
23
+ expect(w.tokenaddr!).toBe(ADDRESS_TOKEN);
24
+ let w2 = await RegTestWallet.watchOnly(w.cashaddr!);
25
+
26
+ expect(w2.address!).toBe(ADDRESS);
27
+ expect(w2.cashaddr!).toBe(ADDRESS);
28
+ expect(w2.tokenaddr!).toBe(ADDRESS_TOKEN);
29
+
30
+ let w3 = await RegTestWallet.watchOnly(ADDRESS_TOKEN);
31
+ expect(w3.address!).toBe(ADDRESS);
32
+ expect(w3.cashaddr!).toBe(ADDRESS);
33
+ expect(w3.tokenaddr!).toBe(ADDRESS_TOKEN);
34
+ });
35
+
36
+ test("Get create a p2sh32 watch address", async () => {
37
+ const ADDRESS =
38
+ "bitcoincash:pvykylj7uk385669fjse37r2eknx35ngaalx805q2hul62lmx2fq2v5dx6g8w";
39
+
40
+ let w = await Wallet.watchOnly(
41
+ "bitcoincash:pvykylj7uk385669fjse37r2eknx35ngaalx805q2hul62lmx2fq2v5dx6g8w"
42
+ );
43
+
44
+ expect(w.cashaddr!.startsWith("bitcoincash:")).toBeTruthy();
45
+ expect(w.address!).toBe(ADDRESS);
46
+ });
47
+
48
+ test("Get create a p2sh watch address", async () => {
49
+ const ADDRESS = "bitcoincash:pzvts0uztwg32yvrx7xz9lp572dgnt20sy0dj993vx";
50
+
51
+ let w = await Wallet.watchOnly(
52
+ "bitcoincash:pzvts0uztwg32yvrx7xz9lp572dgnt20sy0dj993vx"
53
+ );
54
+
55
+ expect(w.cashaddr!.startsWith("bitcoincash:")).toBeTruthy();
56
+ expect(w.address!).toBe(ADDRESS);
57
+ });
58
+ });