Skip to content

Commit 2d2a7ab

Browse files
committed
improvements to signature and publickey, ED support working
1 parent f485980 commit 2d2a7ab

File tree

4 files changed

+62
-59
lines changed

4 files changed

+62
-59
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "@wireio/core",
33
"description": "Library for working with Wire powered blockchains.",
4-
"version": "0.1.7",
4+
"version": "0.1.8",
55
"homepage": "https://github.com/Wire-Network/sdk-core",
66
"license": "FSL-1.1-Apache-2.0",
77
"main": "lib/core.js",

src/api/client.ts

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,9 @@ export interface SignerProvider {
3030

3131
/**
3232
* Sign an arbitrary message payload.
33-
* If you pass a string, it will be UTF-8 → bytes first.
3433
* Returns raw sig bytes as Uint8Array.
3534
*/
36-
signMessage(msg: string | Uint8Array): Promise<Uint8Array>;
35+
sign(msg: string | Uint8Array): Promise<Uint8Array>;
3736
}
3837

3938
export interface APIErrorDetail {
@@ -266,23 +265,26 @@ export class APIClient {
266265
async buildSignedTransaction(action: AnyAction | AnyAction[], opts?: TransactionExtraOptions): Promise<SignedTransaction> {
267266
if (!this.signer) throw new Error('No signer function provided in APIClient options');
268267

269-
const keyType = opts && opts.key_type ? opts.key_type : KeyType.EM;
268+
const keyType = opts && opts.key_type ? opts.key_type : this.signer.keyType;
270269
const actions = await this.anyToAction(action);
271270
const info = await this.v1.chain.get_info();
272271
const header = info.getTransactionHeader();
273272
const transaction = Transaction.from({
274273
...header, actions,
275-
context_free_actions: (opts && opts.context_free_actions) ? opts.context_free_actions : []
274+
context_free_actions: (opts && opts.context_free_actions) ? opts.context_free_actions : [],
275+
transaction_extensions: [{ type: 1, data: [] }]
276276
});
277-
const digest = transaction.signingDigest(info.chain_id);
278-
// const messageBytes = keyType === KeyType.EM
279-
// ? ethers.utils.arrayify('0x' + digest.hexString)
280-
// : digest.hexString;
281-
282-
const messageBytes = Buffer.from(digest.hexString, 'hex');
277+
const msgDigest = transaction.signingDigest(info.chain_id);
278+
let msgBytes: Uint8Array = msgDigest.array;
279+
280+
// Handle keytype specific digest preparation
281+
switch (keyType) {
282+
case KeyType.EM: // Prefix with 0x and arrayify
283+
msgBytes = ethers.utils.arrayify('0x' + msgDigest.hexString);
284+
break;
285+
}
283286

284-
const sigBytes = await this.signer.signMessage(messageBytes).catch(err => { throw new Error(err) });
285-
// const ethHex = ethers.utils.hexlify(ethBytes);
287+
const sigBytes = await this.signer.sign(msgBytes).catch(err => { throw new Error(err) });
286288
const signature = Signature.fromRaw(sigBytes, keyType);
287289
return SignedTransaction.from({ ...transaction, signatures: [signature] });
288290
}

src/chain/signature.ts

Lines changed: 47 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -79,13 +79,15 @@ export class Signature implements ABISerializableObject {
7979
}
8080

8181
const type = KeyType.from(parts[1]);
82-
// 65 for ECDSA, 64 for ED
82+
// 65 for all wire-format curves (we now pad ED to 65 bytes)
8383
const size =
84-
type === KeyType.K1 || type === KeyType.R1 || type === KeyType.EM
84+
(type === KeyType.K1 ||
85+
type === KeyType.R1 ||
86+
type === KeyType.EM ||
87+
type === KeyType.ED)
8588
? 65
86-
: type === KeyType.ED
87-
? 64
88-
: undefined;
89+
: undefined;
90+
8991
const data = Base58.decodeRipemd160Check(parts[2], size, type);
9092
return new Signature(type, data);
9193
}
@@ -105,9 +107,8 @@ export class Signature implements ABISerializableObject {
105107
return new Signature(KeyType.WA, data);
106108
}
107109

108-
// read 64 bytes for ED, 65 for everything else
109-
const len = type === KeyType.ED ? 64 : 65;
110-
return new Signature(type, new Bytes(decoder.readArray(len)));
110+
const length = 65;
111+
return new Signature(type, new Bytes(decoder.readArray(length)));
111112
}
112113

113114
/**
@@ -121,38 +122,6 @@ export class Signature implements ABISerializableObject {
121122
const h = hexStr.startsWith('0x') ? hexStr.slice(2) : hexStr;
122123
const raw = Uint8Array.from(Buffer.from(h, 'hex'));
123124
return Signature.fromRaw(raw, type);
124-
125-
// const h = hexStr.startsWith('0x') ? hexStr.slice(2) : hexStr;
126-
127-
// if (type === KeyType.ED) {
128-
// if (h.length !== 128) {
129-
// throw new Error(`ED25519 hex must be 128 chars, got ${h.length}`);
130-
// }
131-
132-
// // decode all 64 bytes at once
133-
// const raw = Uint8Array.from(Buffer.from(h, 'hex'));
134-
// return new Signature(KeyType.ED, new Bytes(raw));
135-
// }
136-
137-
// // non-ED: expect 65 bytes → 130 hex chars
138-
// if (h.length !== 130) {
139-
// throw new Error(`ECDSA/EM hex must be 130 chars, got ${h.length}`);
140-
// }
141-
142-
// const buf = Uint8Array.from(Buffer.from(h, 'hex'));
143-
// // split off r, s, v
144-
// const r = buf.slice(0, 32);
145-
// const s = buf.slice(32, 64);
146-
// let recid = buf[64];
147-
// // Ethereum v (27/28) → wire recid (31/32) = v + 4
148-
// recid += 4;
149-
150-
// const arr = new Uint8Array(1 + 32 + 32);
151-
// arr[0] = recid;
152-
// arr.set(r, 1);
153-
// arr.set(s, 33);
154-
155-
// return new Signature(type, new Bytes(arr));
156125
}
157126

158127
/**
@@ -164,7 +133,11 @@ export class Signature implements ABISerializableObject {
164133
// ED25519: the raw is already [r‖s]
165134
if (type === KeyType.ED) {
166135
if (raw.length !== 64) throw new Error(`ED raw sig must be 64 bytes, got ${raw.length}`);
167-
return new Signature(type, new Bytes(raw));
136+
// ► pad to 65 bytes with a zero at the end:
137+
const wire = new Uint8Array(65);
138+
wire.set(raw, 0);
139+
wire[64] = 0;
140+
return new Signature(type, new Bytes(wire));
168141
}
169142

170143
// ECDSA/EIP-191: raw should be 65 bytes [r‖s‖v]
@@ -204,8 +177,35 @@ export class Signature implements ABISerializableObject {
204177
* - ED: 64 bytes `[r(32)‖s(32)]`
205178
*/
206179
constructor(type: KeyType, data: Bytes | Uint8Array) {
180+
let wire: Uint8Array;
181+
182+
if (type === KeyType.ED) {
183+
const arr = data instanceof Bytes ? data.array : data;
184+
185+
if (arr.length === 64) {
186+
// pad to 65 so toString() and from() agree
187+
wire = new Uint8Array(65);
188+
wire.set(arr, 0);
189+
wire[64] = 0;
190+
} else if (arr.length === 65) {
191+
// already padded
192+
wire = arr;
193+
} else {
194+
throw new Error(`ED signature must be 64 or 65 bytes, got ${arr.length}`);
195+
}
196+
} else {
197+
// everything else: expect exactly 65 bytes already in wire-format
198+
const arr = data instanceof Bytes ? data.array : data;
199+
200+
if (arr.length !== 65) {
201+
throw new Error(`Expected 65-byte wire format for ${type}, got ${arr.length}`);
202+
}
203+
204+
wire = arr;
205+
}
206+
207207
this.type = type;
208-
this.data = data instanceof Bytes ? data : new Bytes(data);
208+
this.data = new Bytes(wire);
209209
}
210210

211211
equals(other: SignatureType): boolean {
@@ -251,9 +251,11 @@ export class Signature implements ABISerializableObject {
251251
const rawMsg = Bytes.from(message).array;
252252

253253
switch (this.type) {
254-
case KeyType.ED:
255-
// ED25519: raw `[r‖s]`
256-
return Crypto.verify(this.data.array, rawMsg, publicKey.data.array, this.type);
254+
case KeyType.ED: {
255+
// ED25519: storage is [r||s||0], TweetNaCl needs exactly 64 bytes [r||s] - strip padded 0
256+
const sig64 = this.data.array.subarray(0, 64);
257+
return Crypto.verify(sig64, rawMsg, publicKey.data.array, this.type);
258+
}
257259

258260
case KeyType.EM: {
259261
// 1) unwrap wire [vWire‖r‖s]

test/api.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,6 @@ suite('api v1', function () {
139139
assert.instanceOf(response.account_name, Name);
140140
assert.equal(response.account_name, 'eosio.token');
141141

142-
console.log(response.code_hash);
143142
assert.instanceOf(response.code_hash, Checksum256);
144143
assert.equal(
145144
response.code_hash,

0 commit comments

Comments
 (0)