Skip to content

Commit ea01587

Browse files
authored
feat: [Stacks 2.1] delegate-stx Bitcoin-op parsing (#1527)
* feat: initial event parsing for `delegate-stx` pox2 event * feat: create synthetic tx from parsing DelegateStx pox2 event data * feat: parsing of optional `pox-addr` arg of `delegate-stx` event * feat: parsing of optional `until-burn-ht` arg of `delegate-stx` event * test: validate pox2 event for `delegate-stx` Stacks-chain op * chore: remove accidentally committed code * chore: bump to Stacks node `v2.1.0.0.0-rc4` * ci: do not fail-fast on 2.1 test matrix * test: temp disable tests that are flaking with stacks-node 2.1-RC4 * test: try waiting for next pox cycle in btc-address-format stacking tests * test: try waiting for next pox cycle in btc-address-format stacking tests, attempt 2
1 parent 33d0d32 commit ea01587

18 files changed

+370
-24
lines changed

.github/workflows/ci.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -403,6 +403,7 @@ jobs:
403403

404404
test-2_1:
405405
strategy:
406+
fail-fast: false
406407
matrix:
407408
suite: [
408409
block-zero-handling,
@@ -478,6 +479,7 @@ jobs:
478479

479480
test-2_1-transition:
480481
strategy:
482+
fail-fast: false
481483
matrix:
482484
suite:
483485
[

docker/docker-compose.dev.stacks-krypton-2.1-transition.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
version: '3.7'
22
services:
33
stacks-blockchain:
4-
image: "zone117x/stacks-api-e2e:stacks2.1-transition-7e78d0a"
4+
image: "zone117x/stacks-api-e2e:stacks2.1-transition-38c5623"
55
ports:
66
- "18443:18443" # bitcoin regtest JSON-RPC interface
77
- "18444:18444" # bitcoin regtest p2p

docker/docker-compose.dev.stacks-krypton.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
version: '3.7'
22
services:
33
stacks-blockchain:
4-
image: "zone117x/stacks-api-e2e:stacks2.1-7e78d0a"
4+
image: "zone117x/stacks-api-e2e:stacks2.1-38c5623"
55
ports:
66
- "18443:18443" # bitcoin regtest JSON-RPC interface
77
- "18444:18444" # bitcoin regtest p2p

migrations/1666703991492_pox_events.js

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,9 @@ exports.up = pgm => {
9696
first_unlocked_cycle: { // unique to handle-unlock
9797
type: 'numeric',
9898
},
99+
delegate_to: { // unique to delegate-stx
100+
type: 'string',
101+
},
99102
lock_period: { // unique to stack-stx, delegate-stack-stx
100103
type: 'numeric'
101104
},
@@ -105,7 +108,7 @@ exports.up = pgm => {
105108
start_burn_height: { // unique to stack-stx, delegate-stack-stx
106109
type: 'numeric',
107110
},
108-
unlock_burn_height: { // unique to stack-stx, stack-extend, delegate-stack-stx, delegate-stack-extend
111+
unlock_burn_height: { // unique to stack-stx, stack-extend, delegate-stack-stx, delegate-stack-extend, delegate-stx
109112
type: 'numeric',
110113
},
111114
delegator: { // unique to delegate-stack-stx, delegate-stack-increase, delegate-stack-extend
@@ -123,7 +126,7 @@ exports.up = pgm => {
123126
reward_cycle: { // unique to stack-aggregation-*
124127
type: 'numeric',
125128
},
126-
amount_ustx: { // unique to stack-aggregation-*
129+
amount_ustx: { // unique to stack-aggregation-*, delegate-stx
127130
type: 'numeric',
128131
},
129132
});
@@ -144,6 +147,9 @@ exports.up = pgm => {
144147
WHEN 'stack-extend' THEN
145148
extend_count IS NOT NULL AND
146149
unlock_burn_height IS NOT NULL
150+
WHEN 'delegate-stx' THEN
151+
amount_ustx IS NOT NULL AND
152+
delegate_to IS NOT NULL
147153
WHEN 'delegate-stack-stx' THEN
148154
lock_period IS NOT NULL AND
149155
lock_amount IS NOT NULL AND

src/api/controllers/db-controller.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,16 @@ export function parsePox2Event(poxEvent: DbPox2Event) {
255255
},
256256
};
257257
}
258+
case Pox2EventName.DelegateStx: {
259+
return {
260+
...baseInfo,
261+
data: {
262+
amount_ustx: poxEvent.data.amount_ustx.toString(),
263+
delegate_to: poxEvent.data.delegate_to,
264+
unlock_burn_height: poxEvent.data.unlock_burn_height?.toString(),
265+
},
266+
};
267+
}
258268
case Pox2EventName.DelegateStackStx: {
259269
return {
260270
...baseInfo,

src/datastore/common.ts

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -348,6 +348,15 @@ export interface DbPox2StackExtendEvent extends DbPox2BaseEventData {
348348
};
349349
}
350350

351+
export interface DbPox2DelegateStxEvent extends DbPox2BaseEventData {
352+
name: Pox2EventName.DelegateStx;
353+
data: {
354+
amount_ustx: bigint;
355+
delegate_to: string;
356+
unlock_burn_height: bigint | null;
357+
};
358+
}
359+
351360
export interface DbPox2DelegateStackStxEvent extends DbPox2BaseEventData {
352361
name: Pox2EventName.DelegateStackStx;
353362
data: {
@@ -406,6 +415,7 @@ export type DbPox2EventData =
406415
| DbPox2StackStxEvent
407416
| DbPox2StackIncreaseEvent
408417
| DbPox2StackExtendEvent
418+
| DbPox2DelegateStxEvent
409419
| DbPox2DelegateStackStxEvent
410420
| DbPox2DelegateStackIncreaseEvent
411421
| DbPox2DelegateStackExtendEvent
@@ -1227,12 +1237,15 @@ export interface Pox2EventQueryResult {
12271237
// unique to stack-stx, delegate-stack-stx
12281238
start_burn_height: string | null;
12291239

1230-
// unique to stack-stx, stack-extend, delegate-stack-stx, delegate-stack-extend
1240+
// unique to stack-stx, stack-extend, delegate-stack-stx, delegate-stack-extend, delegate-stx
12311241
unlock_burn_height: string | null;
12321242

12331243
// unique to delegate-stack-stx, delegate-stack-increase, delegate-stack-extend
12341244
delegator: string | null;
12351245

1246+
// unique to delegate-stx
1247+
delegate_to: string | null;
1248+
12361249
// unique to stack-increase, delegate-stack-increase
12371250
increase_by: string | null;
12381251

@@ -1245,7 +1258,7 @@ export interface Pox2EventQueryResult {
12451258
// unique to stack-aggregation-commit
12461259
reward_cycle: string | null;
12471260

1248-
// unique to stack-aggregation-commit
1261+
// unique to stack-aggregation-commit, delegate-stx
12491262
amount_ustx: string | null;
12501263
}
12511264

@@ -1274,6 +1287,9 @@ export interface Pox2EventInsertValues {
12741287
// unique to handle-unlock
12751288
first_unlocked_cycle: PgNumeric | null;
12761289

1290+
// unique to delegate-stx
1291+
delegate_to: string | null;
1292+
12771293
// unique to stack-stx, delegate-stack-stx
12781294
lock_period: PgNumeric | null;
12791295

@@ -1300,7 +1316,7 @@ export interface Pox2EventInsertValues {
13001316
// unique to stack-aggregation-commit
13011317
reward_cycle: PgNumeric | null;
13021318

1303-
// unique to stack-aggregation-commit
1319+
// unique to stack-aggregation-commit, delegate-stx
13041320
amount_ustx: PgNumeric | null;
13051321
}
13061322

src/datastore/helpers.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import {
1818
DbPox2DelegateStackExtendEvent,
1919
DbPox2DelegateStackIncreaseEvent,
2020
DbPox2DelegateStackStxEvent,
21+
DbPox2DelegateStxEvent,
2122
DbPox2Event,
2223
DbPox2HandleUnlockEvent,
2324
DbPox2StackAggregationCommitEvent,
@@ -216,6 +217,7 @@ export const POX2_EVENT_COLUMNS = [
216217
'start_burn_height',
217218
'unlock_burn_height',
218219
'delegator',
220+
'delegate_to',
219221
'increase_by',
220222
'total_locked',
221223
'extend_count',
@@ -693,6 +695,23 @@ export function parseDbPox2Event(row: Pox2EventQueryResult): DbPox2Event {
693695
...eventData,
694696
};
695697
}
698+
case Pox2EventName.DelegateStx: {
699+
const eventData: DbPox2DelegateStxEvent = {
700+
...basePox2Event,
701+
name: rowName,
702+
data: {
703+
amount_ustx: BigInt(unwrapOptionalProp(row, 'amount_ustx')),
704+
delegate_to: unwrapOptionalProp(row, 'delegate_to'),
705+
unlock_burn_height: row.unlock_burn_height
706+
? BigInt(unwrapOptionalProp(row, 'unlock_burn_height'))
707+
: null,
708+
},
709+
};
710+
return {
711+
...baseEvent,
712+
...eventData,
713+
};
714+
}
696715
case Pox2EventName.DelegateStackStx: {
697716
const eventData: DbPox2DelegateStackStxEvent = {
698717
...basePox2Event,

src/datastore/pg-write-store.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -819,6 +819,7 @@ export class PgWriteStore extends PgStore {
819819
pox_addr_raw: event.pox_addr_raw,
820820
first_cycle_locked: null,
821821
first_unlocked_cycle: null,
822+
delegate_to: null,
822823
lock_period: null,
823824
lock_amount: null,
824825
start_burn_height: null,
@@ -854,6 +855,12 @@ export class PgWriteStore extends PgStore {
854855
values.unlock_burn_height = event.data.unlock_burn_height.toString();
855856
break;
856857
}
858+
case Pox2EventName.DelegateStx: {
859+
values.amount_ustx = event.data.amount_ustx.toString();
860+
values.delegate_to = event.data.delegate_to;
861+
values.unlock_burn_height = event.data.unlock_burn_height?.toString() ?? null;
862+
break;
863+
}
857864
case Pox2EventName.DelegateStackStx: {
858865
values.lock_period = event.data.lock_period.toString();
859866
values.lock_amount = event.data.lock_amount.toString();

src/ec-helpers.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,7 @@ export interface VerboseKeyOutput {
216216
publicKey: Buffer;
217217
}
218218

219-
type BitcoinAddressFormat =
219+
export type BitcoinAddressFormat =
220220
| 'p2pkh'
221221
| 'p2sh'
222222
| 'p2sh-p2wpkh'

src/event-stream/pox2-event-parsing.ts

Lines changed: 44 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import {
33
DbPox2DelegateStackExtendEvent,
44
DbPox2DelegateStackIncreaseEvent,
55
DbPox2DelegateStackStxEvent,
6+
DbPox2DelegateStxEvent,
67
DbPox2EventData,
78
DbPox2HandleUnlockEvent,
89
DbPox2StackAggregationCommitEvent,
@@ -19,6 +20,8 @@ import {
1920
ClarityValue,
2021
ClarityValueAbstract,
2122
ClarityValueBuffer,
23+
ClarityValueOptionalNone,
24+
ClarityValueOptionalSome,
2225
ClarityValuePrincipalContract,
2326
ClarityValuePrincipalStandard,
2427
ClarityValueResponse,
@@ -31,10 +34,19 @@ import { poxAddressToBtcAddress } from '@stacks/stacking';
3134
import { Pox2EventName } from '../pox-helpers';
3235

3336
function tryClarityPoxAddressToBtcAddress(
34-
poxAddr: Pox2Addr,
37+
poxAddr: Pox2Addr | ClarityValueOptionalSome<Pox2Addr> | ClarityValueOptionalNone,
3538
network: 'mainnet' | 'testnet' | 'regtest'
3639
): { btcAddr: string | null; raw: Buffer } {
3740
let btcAddr: string | null = null;
41+
if (poxAddr.type_id === ClarityTypeID.OptionalNone) {
42+
return {
43+
btcAddr,
44+
raw: Buffer.alloc(0),
45+
};
46+
}
47+
if (poxAddr.type_id === ClarityTypeID.OptionalSome) {
48+
poxAddr = poxAddr.value;
49+
}
3850
try {
3951
btcAddr = poxAddressToBtcAddress(
4052
coerceToBuffer(poxAddr.data.version.buffer)[0],
@@ -91,6 +103,12 @@ interface Pox2PrintEventTypes {
91103
'unlock-burn-height': ClarityValueUInt;
92104
'pox-addr': Pox2Addr;
93105
};
106+
[Pox2EventName.DelegateStx]: {
107+
'amount-ustx': ClarityValueUInt;
108+
'delegate-to': ClarityValuePrincipalStandard | ClarityValuePrincipalContract;
109+
'unlock-burn-height': ClarityValueOptionalSome<ClarityValueUInt> | ClarityValueOptionalNone;
110+
'pox-addr': Pox2Addr | ClarityValueOptionalNone;
111+
};
94112
[Pox2EventName.DelegateStackStx]: {
95113
'lock-amount': ClarityValueUInt;
96114
'unlock-burn-height': ClarityValueUInt;
@@ -191,7 +209,10 @@ export function decodePox2PrintEvent(
191209
}
192210

193211
if ('pox-addr' in eventData) {
194-
const eventPoxAddr = eventData['pox-addr'] as Pox2Addr;
212+
const eventPoxAddr = eventData['pox-addr'] as
213+
| Pox2Addr
214+
| ClarityValueOptionalSome<Pox2Addr>
215+
| ClarityValueOptionalNone;
195216
const encodedArr = tryClarityPoxAddressToBtcAddress(eventPoxAddr, network);
196217
baseEventData.pox_addr = encodedArr.btcAddr;
197218
baseEventData.pox_addr_raw = bufferToHexPrefixString(encodedArr.raw);
@@ -264,6 +285,27 @@ export function decodePox2PrintEvent(
264285
}
265286
return parsedData;
266287
}
288+
case Pox2EventName.DelegateStx: {
289+
const d = eventData as Pox2PrintEventTypes[typeof eventName];
290+
const parsedData: DbPox2DelegateStxEvent = {
291+
...baseEventData,
292+
name: eventName,
293+
data: {
294+
amount_ustx: BigInt(d['amount-ustx'].value),
295+
delegate_to: clarityPrincipalToFullAddress(d['delegate-to']),
296+
unlock_burn_height:
297+
d['unlock-burn-height'].type_id === ClarityTypeID.OptionalSome
298+
? BigInt(d['unlock-burn-height'].value.value)
299+
: null,
300+
},
301+
};
302+
if (PATCH_EVENT_BALANCES) {
303+
if (parsedData.data.unlock_burn_height) {
304+
parsedData.burnchain_unlock_height = parsedData.data.unlock_burn_height;
305+
}
306+
}
307+
return parsedData;
308+
}
267309
case Pox2EventName.DelegateStackStx: {
268310
const d = eventData as Pox2PrintEventTypes[typeof eventName];
269311
const parsedData: DbPox2DelegateStackStxEvent = {

0 commit comments

Comments
 (0)