Skip to content

Commit 0950a20

Browse files
OttoAllmendingerllm-git
andcommitted
fix(utxo-staking): support BIP-322 for delegation signatures
Update babylonlabs-io-btc-staking-ts to v1.0.0 and add BIP-322 implementation for proof-of-possession signatures in delegation messages, handling both ECDSA and BIP-322-simple signature types. Issue: BTC-2032 Co-authored-by: llm-git <[email protected]> Ci-retry: 1
1 parent f5babca commit 0950a20

File tree

7 files changed

+133
-34
lines changed

7 files changed

+133
-34
lines changed

modules/utxo-staking/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,11 +43,12 @@
4343
},
4444
"dependencies": {
4545
"@babylonlabs-io/babylon-proto-ts": "1.0.0",
46-
"@bitgo/babylonlabs-io-btc-staking-ts": "^0.5.0",
46+
"@bitgo/babylonlabs-io-btc-staking-ts": "^1.0.0",
4747
"@bitgo/unspents": "^0.47.21",
4848
"@bitgo/utxo-core": "^1.8.0",
4949
"@bitgo/utxo-lib": "^11.3.0",
5050
"@bitgo/wasm-miniscript": "2.0.0-beta.7",
51+
"bip322-js": "^2.0.0",
5152
"bitcoinjs-lib": "^6.1.7",
5253
"fp-ts": "^2.16.2",
5354
"io-ts": "npm:@bitgo-forks/[email protected]",

modules/utxo-staking/src/babylon/delegationMessage.ts

Lines changed: 40 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,14 @@
33
*/
44
import assert from 'assert';
55

6+
import { BIP322 } from 'bip322-js';
67
import * as vendor from '@bitgo/babylonlabs-io-btc-staking-ts';
78
import * as babylonProtobuf from '@babylonlabs-io/babylon-proto-ts';
89
import * as bitcoinjslib from 'bitcoinjs-lib';
910
import * as utxolib from '@bitgo/utxo-lib';
1011
import { Descriptor } from '@bitgo/wasm-miniscript';
1112
import { toXOnlyPublicKey } from '@bitgo/utxo-core';
12-
import { toWrappedPsbt } from '@bitgo/utxo-core/descriptor';
13+
import { signWithKey, toWrappedPsbt } from '@bitgo/utxo-core/descriptor';
1314

1415
import { BabylonDescriptorBuilder } from './descriptor';
1516
import { createStakingManager } from './stakingManager';
@@ -72,20 +73,55 @@ export function getBtcProviderForECKey(
7273
return psbt;
7374
}
7475

76+
function signBip322Simple(message: string): string {
77+
// Get the script public key from the staking descriptor
78+
const scriptPubKey = Buffer.from(descriptorBuilder.getStakingDescriptor().scriptPubkey());
79+
const toSpendTx = BIP322.buildToSpendTx(message, scriptPubKey);
80+
81+
// Get the to_spend txid
82+
const toSpendTxId = toSpendTx.getId();
83+
84+
// Create PSBT object for constructing the transaction
85+
const toSignPsbt = new bitcoinjslib.Psbt();
86+
toSignPsbt.setVersion(2); // nVersion = 0
87+
toSignPsbt.setLocktime(0); // nLockTime = 0
88+
toSignPsbt.addInput({
89+
hash: toSpendTxId,
90+
index: 0,
91+
sequence: descriptorBuilder.stakingTimeLock,
92+
witnessUtxo: {
93+
script: scriptPubKey,
94+
value: 0,
95+
},
96+
});
97+
98+
// Sign the PSBT with the staker key
99+
const wrappedPsbt = toWrappedPsbt(toSignPsbt.toBuffer());
100+
wrappedPsbt.updateInputWithDescriptor(0, descriptorBuilder.getStakingDescriptor());
101+
signWithKey(wrappedPsbt, stakerKey);
102+
wrappedPsbt.finalize();
103+
104+
// Encode the witness data and return
105+
return BIP322.encodeWitness(bitcoinjslib.Psbt.fromBuffer(Buffer.from(wrappedPsbt.serialize())));
106+
}
107+
75108
return {
76109
async signMessage(
77110
signingStep: vendor.SigningStep,
78111
message: string,
79112
type: 'ecdsa' | 'bip322-simple'
80113
): Promise<string> {
81-
assert(type === 'ecdsa');
82-
switch (signingStep) {
83-
case 'proof-of-possession':
114+
assert(signingStep === 'proof-of-possession');
115+
switch (type) {
116+
case 'ecdsa':
84117
return stakerKey.sign(Buffer.from(message, 'hex')).toString('hex');
118+
case 'bip322-simple':
119+
return signBip322Simple(message);
85120
default:
86121
throw new Error(`unexpected signing step: ${signingStep}`);
87122
}
88123
},
124+
89125
async signPsbt(signingStep: vendor.SigningStep, psbtHex: string): Promise<string> {
90126
const psbt = bitcoinjslib.Psbt.fromHex(psbtHex);
91127
switch (signingStep) {
@@ -99,7 +135,6 @@ export function getBtcProviderForECKey(
99135
},
100136
};
101137
}
102-
103138
type Result = {
104139
unsignedDelegationMsg: ValueWithTypeUrl<babylonProtobuf.btcstakingtx.MsgCreateBTCDelegation>;
105140
stakingTx: bitcoinjslib.Transaction;

modules/utxo-staking/test/fixtures/babylon/msgCreateBTCDelegation.testnet.json

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44
"value": {
55
"stakerAddr": "bbn1qw3jhxaqax8rcq",
66
"pop": {
7-
"btcSigType": 2,
8-
"btcSig": "77d73c7deef77de75f6dc79cddaf7c7f8f3aedbddcd36f787f6d35d37dfaf5d7dbdb46b9efb71e71de79f3cf74e7a6b7e9ff7475ae3c6da7dc7b9e7ae9cf74e1deb46dc6dcd5bd377b6df6e3be7475feddf3d71bd7c7757fa7dc6ddd3adf4ddb"
7+
"btcSigType": 1,
8+
"btcSig": "0a2a626331713339683368666a6161743473676b616e7a67307a7065743566656e7635726a67306c686e767912cb010340478d18ba3a60afb23a603cbfc3023b3253d1ca0b44053b47bd8e9de2d6aa8efd946ea42c6a2b35deb897c0ed308e1c1b6463a1055a10e6dc5042b610e01af47126207b6a08504c46336f985a5787a5423eb18c10b149fef29cd3316ad86f565cd2b9ad021027b261c050929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac01e1d2e84c4fc6bdddf3b8018065cf5ca8405988579188585f382c51c088e882696962cb69242e00941e0a6197b7ecdb83ab8bb0490dbfd23fa4b8d26b75989eb"
99
},
1010
"btcPk": "7b6a08504c46336f985a5787a5423eb18c10b149fef29cd3316ad86f565cd2b9",
1111
"fpBtcPkList": [
@@ -14,13 +14,13 @@
1414
"stakingTime": 10000,
1515
"stakingValue": 55555,
1616
"stakingTx": "020000000111111111111111111111111111111111111111111111111111111111111111110000000000ffffffff0203d9000000000000225120f1871fc2ac3050b53dc35d502a9d94388f6f373b86f3905667945a8430cbd639bf51090000000000160014896f1ba65deaeb045bb3121e20e5744e66ca0e4800000000",
17-
"slashingTx": "020000000164da14050ffd0e6186c68a59f371a0adc95cc84b0502fe0915be7eba3f771bb30000000000ffffffff02d90a0000000000001600145be12624d08a2b424095d7c07221c33450d14bf1a2ba000000000000225120d5238530e223ef1bd34a8a98ee1708f6a8a87e7a2589d88de6700b9973ffff4600000000",
18-
"delegatorSlashingSig": "f10a5e6d722b459e87d713bf9af1113fa5eb7a1e41ff5738de7049fcf113beaa5f01228aecf27eb94045a9900b092091a63dbf546fd7d6c05d32d32cf8ad591d",
17+
"slashingTx": "020000000164da14050ffd0e6186c68a59f371a0adc95cc84b0502fe0915be7eba3f771bb30000000000ffffffff02da0a0000000000001600145be12624d08a2b424095d7c07221c33450d14bf1a1ba000000000000225120d5238530e223ef1bd34a8a98ee1708f6a8a87e7a2589d88de6700b9973ffff4600000000",
18+
"delegatorSlashingSig": "3da4c633225c7cc2f5b2db78f9126be6f896c8f8facb4e8a8358194fb4c24abaa6e799923d1fe6b607aafc5e45a9b7a18937e3d1231a7dcbfc199df325299e37",
1919
"unbondingTime": 1008,
2020
"unbondingTx": "020000000164da14050ffd0e6186c68a59f371a0adc95cc84b0502fe0915be7eba3f771bb30000000000ffffffff0133d10000000000002251204dcea0c802236110602d7b1cc2e76ef5f1f05170b058685b4caf4367ac849d6b00000000",
2121
"unbondingValue": 53555,
22-
"unbondingSlashingTx": "0200000001c047c5904542017cfee57fdb350d6bf776a5ef8c46bc033f454a64b496d0ab9d0000000000ffffffff02750a0000000000001600145be12624d08a2b424095d7c07221c33450d14bf136b3000000000000225120d5238530e223ef1bd34a8a98ee1708f6a8a87e7a2589d88de6700b9973ffff4600000000",
23-
"delegatorUnbondingSlashingSig": "5bf9bed637fbd109d53c60df4093b166ba06a27b90c6b7d05beb9124a19fc62d1d17522a309d4dd7d8dc2eed954dcb3f628f44ae9837c02b91545fa313de6e17"
22+
"unbondingSlashingTx": "0200000001c047c5904542017cfee57fdb350d6bf776a5ef8c46bc033f454a64b496d0ab9d0000000000ffffffff02760a0000000000001600145be12624d08a2b424095d7c07221c33450d14bf135b3000000000000225120d5238530e223ef1bd34a8a98ee1708f6a8a87e7a2589d88de6700b9973ffff4600000000",
23+
"delegatorUnbondingSlashingSig": "c53c4747e7b4a6177f73d3adc80158088141d7c30d11b5a8be2bb6b1d3acefb3d685391e67add3056982a9989877e20bc82feee844c46dea81a67ab22caf6541"
2424
}
2525
},
2626
"stakingTx": {

modules/utxo-staking/test/fixtures/babylon/msgCreateBTCDelegation.testnetMock.json

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44
"value": {
55
"stakerAddr": "bbn1qw3jhxaqax8rcq",
66
"pop": {
7-
"btcSigType": 2,
8-
"btcSig": "77d73c7deef77de75f6dc79cddaf7c7f8f3aedbddcd36f787f6d35d37dfaf5d7dbdb46b9efb71e71de79f3cf74e7a6b7e9ff7475ae3c6da7dc7b9e7ae9cf74e1deb46dc6dcd5bd377b6df6e3be7475feddf3d71bd7c7757fa7dc6ddd3adf4ddb"
7+
"btcSigType": 1,
8+
"btcSig": "0a2a626331713339683368666a6161743473676b616e7a67307a7065743566656e7635726a67306c686e767912cb0103404b7729f55fa3d0b0da10357db45a72acf372932e142ce3febc429f20db3b11c0fac2a479d027897a30f00b479024c96ef7ad46a4afc1048042f1cac3cc00344a26207b6a08504c46336f985a5787a5423eb18c10b149fef29cd3316ad86f565cd2b9ad021027b261c150929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac068cc9790c0627bc8f28afd009b31974a2fce5ea4fe2ed4dd8b65c8feda196875c1d262cfe1f3b746337f6766e31854333d370f733bd845727aaed2baebc7a552"
99
},
1010
"btcPk": "7b6a08504c46336f985a5787a5423eb18c10b149fef29cd3316ad86f565cd2b9",
1111
"fpBtcPkList": [
@@ -14,13 +14,13 @@
1414
"stakingTime": 10000,
1515
"stakingValue": 55555,
1616
"stakingTx": "020000000111111111111111111111111111111111111111111111111111111111111111110000000000ffffffff0203d9000000000000225120788d73d75d7dd88d3612f7a91d5b3d6ad4778d8b49176f9539d322980b2f4fd7bf51090000000000160014896f1ba65deaeb045bb3121e20e5744e66ca0e4800000000",
17-
"slashingTx": "0200000001a999d7bc6af1a17cd4e70d0fd875a1734152dfb55f9166240f35965c79fa36c20000000000ffffffff02d90a0000000000001600145be12624d08a2b424095d7c07221c33450d14bf1a2ba000000000000225120d5238530e223ef1bd34a8a98ee1708f6a8a87e7a2589d88de6700b9973ffff4600000000",
18-
"delegatorSlashingSig": "c032a98f7d16adc8a1438310782b35aa0e5d23abca1deb1d743461e7649e0cca07b030c2f083ffb21b88b8de1198a919853b576a7e9c4b80f5bcd6cb544536b4",
17+
"slashingTx": "0200000001a999d7bc6af1a17cd4e70d0fd875a1734152dfb55f9166240f35965c79fa36c20000000000ffffffff02da0a0000000000001600145be12624d08a2b424095d7c07221c33450d14bf1a1ba000000000000225120d5238530e223ef1bd34a8a98ee1708f6a8a87e7a2589d88de6700b9973ffff4600000000",
18+
"delegatorSlashingSig": "2474337cd33ad60d0de8405f5be6b844c5c135184b77aaee623c4b151e30d533b9ff837821d5d85e9a758c79193244e1bfd3fec42208cc1eca993f318bd77566",
1919
"unbondingTime": 1008,
2020
"unbondingTx": "0200000001a999d7bc6af1a17cd4e70d0fd875a1734152dfb55f9166240f35965c79fa36c20000000000ffffffff0133d1000000000000225120dec7bc887b110e2c10f1c9a2212cd961e95184870c91d88c9a3727f4ef4c303c00000000",
2121
"unbondingValue": 53555,
22-
"unbondingSlashingTx": "02000000014c2a294c5e31886937d0985e69e65314419e8866e5ab859cb2903cbe420a555a0000000000ffffffff02750a0000000000001600145be12624d08a2b424095d7c07221c33450d14bf136b3000000000000225120d5238530e223ef1bd34a8a98ee1708f6a8a87e7a2589d88de6700b9973ffff4600000000",
23-
"delegatorUnbondingSlashingSig": "71fdbb1e85db78b2406f7f6a8bbbeecd9be27d6099c4b80b2cf09403a855b55d057805576afad3bf92b79487e9559ad355c9728f95fe191c7a78b21284925fd0"
22+
"unbondingSlashingTx": "02000000014c2a294c5e31886937d0985e69e65314419e8866e5ab859cb2903cbe420a555a0000000000ffffffff02760a0000000000001600145be12624d08a2b424095d7c07221c33450d14bf135b3000000000000225120d5238530e223ef1bd34a8a98ee1708f6a8a87e7a2589d88de6700b9973ffff4600000000",
23+
"delegatorUnbondingSlashingSig": "50f787ffcbd0b4301898767a348615d4e987aa617ad7e06e22b0f249e5660030613a3df2300467aa2376abe2554b98f0499cae686f8e53a07715530c99b1f5fe"
2424
}
2525
},
2626
"stakingTx": {

modules/utxo-staking/test/fixtures/babylon/txTree.testnet.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -190,11 +190,11 @@
190190
],
191191
"outs": [
192192
{
193-
"value": "2677",
193+
"value": "2678",
194194
"script": "00145be12624d08a2b424095d7c07221c33450d14bf1"
195195
},
196196
{
197-
"value": "45878",
197+
"value": "45877",
198198
"script": "5120d5238530e223ef1bd34a8a98ee1708f6a8a87e7a2589d88de6700b9973ffff46"
199199
}
200200
]
@@ -247,11 +247,11 @@
247247
],
248248
"outs": [
249249
{
250-
"value": "2777",
250+
"value": "2778",
251251
"script": "00145be12624d08a2b424095d7c07221c33450d14bf1"
252252
},
253253
{
254-
"value": "47778",
254+
"value": "47777",
255255
"script": "5120d5238530e223ef1bd34a8a98ee1708f6a8a87e7a2589d88de6700b9973ffff46"
256256
}
257257
]

modules/utxo-staking/test/fixtures/babylon/txTree.testnetMock.json

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -190,11 +190,11 @@
190190
],
191191
"outs": [
192192
{
193-
"value": "2677",
193+
"value": "2678",
194194
"script": "00145be12624d08a2b424095d7c07221c33450d14bf1"
195195
},
196196
{
197-
"value": "45878",
197+
"value": "45877",
198198
"script": "5120d5238530e223ef1bd34a8a98ee1708f6a8a87e7a2589d88de6700b9973ffff46"
199199
}
200200
]
@@ -215,7 +215,7 @@
215215
{
216216
"witnessUtxo": {
217217
"script": "5120d5238530e223ef1bd34a8a98ee1708f6a8a87e7a2589d88de6700b9973ffff46",
218-
"value": "45878"
218+
"value": "45877"
219219
},
220220
"tapLeafScript": [
221221
{
@@ -237,7 +237,7 @@
237237
"locktime": 0,
238238
"ins": [
239239
{
240-
"hash": "264b3381598865054722ba6679f12405e06305dc4dd5ad1a6f7c330c28670163",
240+
"hash": "e10ba472c29484735ceeda94f238a9a4bdbd7c9d2a228579a9c09075dc9fa8e0",
241241
"index": 1,
242242
"script": "",
243243
"sequence": 1008,
@@ -246,7 +246,7 @@
246246
],
247247
"outs": [
248248
{
249-
"value": "45590",
249+
"value": "45589",
250250
"script": "0014896f1ba65deaeb045bb3121e20e5744e66ca0e48"
251251
}
252252
]
@@ -299,11 +299,11 @@
299299
],
300300
"outs": [
301301
{
302-
"value": "2777",
302+
"value": "2778",
303303
"script": "00145be12624d08a2b424095d7c07221c33450d14bf1"
304304
},
305305
{
306-
"value": "47778",
306+
"value": "47777",
307307
"script": "5120d5238530e223ef1bd34a8a98ee1708f6a8a87e7a2589d88de6700b9973ffff46"
308308
}
309309
]
@@ -324,7 +324,7 @@
324324
{
325325
"witnessUtxo": {
326326
"script": "5120d5238530e223ef1bd34a8a98ee1708f6a8a87e7a2589d88de6700b9973ffff46",
327-
"value": "47778"
327+
"value": "47777"
328328
},
329329
"tapLeafScript": [
330330
{
@@ -346,7 +346,7 @@
346346
"locktime": 0,
347347
"ins": [
348348
{
349-
"hash": "afdab314f4798317b427a227da4767e0a1c46a37cc14e33e34979aa1eff10ccd",
349+
"hash": "88934f7a4e1b28b6edf69f593ae6c03e94685083f49ce9c0357f515dfc53f8ca",
350350
"index": 1,
351351
"script": "",
352352
"sequence": 1008,
@@ -355,7 +355,7 @@
355355
],
356356
"outs": [
357357
{
358-
"value": "47490",
358+
"value": "47489",
359359
"script": "0014896f1ba65deaeb045bb3121e20e5744e66ca0e48"
360360
}
361361
]

0 commit comments

Comments
 (0)