Merge pull request #1464 from antonilol/lightning-scripts

Detect more lightning scripts
This commit is contained in:
softsimon 2022-04-03 00:28:18 +04:00 committed by GitHub
commit d2fb80fb2c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 44 additions and 43 deletions

View File

@ -1,17 +1,5 @@
<span <span
*ngIf="multisig" *ngIf="label"
class="badge badge-pill badge-warning" class="badge badge-pill badge-warning"
i18n="address-labels.multisig" i18n="address-labels.multisig"
>multisig {{ multisigM }} of {{ multisigN }}</span> >{{ label }}</span>
<span
*ngIf="lightning"
class="badge badge-pill badge-warning"
i18n="address-labels.upper-layer-peg-out"
>Lightning {{ lightning }}</span>
<span
*ngIf="liquid"
class="badge badge-pill badge-warning"
i18n="address-labels.upper-layer-peg-out"
>Liquid {{ liquid }}</span>

View File

@ -14,12 +14,7 @@ export class AddressLabelsComponent implements OnInit {
@Input() vin: Vin; @Input() vin: Vin;
@Input() vout: Vout; @Input() vout: Vout;
multisig = false; label?: string;
multisigM: number;
multisigN: number;
lightning = null;
liquid = null;
constructor( constructor(
stateService: StateService, stateService: StateService,
@ -39,30 +34,46 @@ export class AddressLabelsComponent implements OnInit {
if (this.vin.inner_witnessscript_asm) { if (this.vin.inner_witnessscript_asm) {
if (this.vin.inner_witnessscript_asm.indexOf('OP_DEPTH OP_PUSHNUM_12 OP_EQUAL OP_IF OP_PUSHNUM_11') === 0) { if (this.vin.inner_witnessscript_asm.indexOf('OP_DEPTH OP_PUSHNUM_12 OP_EQUAL OP_IF OP_PUSHNUM_11') === 0) {
if (this.vin.witness.length > 11) { if (this.vin.witness.length > 11) {
this.liquid = 'Peg Out'; this.label = 'Liquid Peg Out';
} else { } else {
this.liquid = 'Emergency Peg Out'; this.label = 'Emergency Liquid Peg Out';
} }
return; return;
} }
// https://github.com/lightning/bolts/blob/master/03-transactions.md#commitment-transaction-outputs const topElement = this.vin.witness[this.vin.witness.length - 2];
if (/^OP_IF OP_PUSHBYTES_33 \w{66} OP_ELSE OP_PUSHBYTES_(1 \w{2}|2 \w{4}) OP_CSV OP_DROP OP_PUSHBYTES_33 \w{66} OP_ENDIF OP_CHECKSIG$/.test(this.vin.inner_witnessscript_asm)) { if (/^OP_IF OP_PUSHBYTES_33 \w{66} OP_ELSE OP_PUSHBYTES_(1 \w{2}|2 \w{4}) OP_CSV OP_DROP OP_PUSHBYTES_33 \w{66} OP_ENDIF OP_CHECKSIG$/.test(this.vin.inner_witnessscript_asm)) {
if (this.vin.witness[this.vin.witness.length - 2] == '01') { // https://github.com/lightning/bolts/blob/master/03-transactions.md#commitment-transaction-outputs
this.lightning = 'Revoked Force Close'; if (topElement === '01') {
// top element is '01' to get in the revocation path
this.label = 'Revoked Lightning Force Close';
} else { } else {
this.lightning = 'Force Close'; // top element is '', this is a delayed to_local output
this.label = 'Lightning Force Close';
} }
// https://github.com/lightning/bolts/blob/master/03-transactions.md#offered-htlc-outputs return;
} else if (/^OP_DUP OP_HASH160 OP_PUSHBYTES_20 \w{40} OP_EQUAL OP_IF OP_CHECKSIG OP_ELSE OP_PUSHBYTES_33 \w{66} OP_SWAP OP_SIZE OP_PUSHBYTES_1 20 OP_EQUAL OP_NOTIF OP_DROP OP_PUSHNUM_2 OP_SWAP OP_PUSHBYTES_33 \w{66} OP_PUSHNUM_2 OP_CHECKMULTISIG OP_ELSE OP_HASH160 OP_PUSHBYTES_20 \w{40} OP_EQUALVERIFY OP_CHECKSIG OP_ENDIF (OP_PUSHNUM_1 OP_CHECKSEQUENCEVERIFY OP_DROP |)OP_ENDIF$/.test(this.vin.inner_witnessscript_asm)) { } else if (/^OP_DUP OP_HASH160 OP_PUSHBYTES_20 \w{40} OP_EQUAL OP_IF OP_CHECKSIG OP_ELSE OP_PUSHBYTES_33 \w{66} OP_SWAP OP_SIZE OP_PUSHBYTES_1 20 OP_EQUAL OP_NOTIF OP_DROP OP_PUSHNUM_2 OP_SWAP OP_PUSHBYTES_33 \w{66} OP_PUSHNUM_2 OP_CHECKMULTISIG OP_ELSE OP_HASH160 OP_PUSHBYTES_20 \w{40} OP_EQUALVERIFY OP_CHECKSIG OP_ENDIF (OP_PUSHNUM_1 OP_CHECKSEQUENCEVERIFY OP_DROP |)OP_ENDIF$/.test(this.vin.inner_witnessscript_asm)) {
if (this.vin.witness[this.vin.witness.length - 2].length == 66) { // https://github.com/lightning/bolts/blob/master/03-transactions.md#offered-htlc-outputs
this.lightning = 'Revoked HTLC'; if (topElement.length === 66) {
// top element is a public key
this.label = 'Revoked Lightning HTLC';
} else if (topElement) {
// top element is a preimage
this.label = 'Lightning HTLC';
} else { } else {
this.lightning = 'HTLC'; // top element is '' to get in the multisig path of the script
this.label = 'Expired Lightning HTLC';
} }
return;
} else if (/^OP_PUSHBYTES_33 \w{66} OP_CHECKSIG OP_IFDUP OP_NOTIF OP_PUSHNUM_16 OP_CSV OP_ENDIF$/.test(this.vin.inner_witnessscript_asm)) {
// https://github.com/lightning/bolts/blob/master/03-transactions.md#to_local_anchor-and-to_remote_anchor-output-option_anchors
if (topElement) {
// top element is a signature
this.label = 'Lightning Anchor';
} else {
// top element is '', it has been swept after 16 blocks
this.label = 'Swept Lightning Anchor';
} }
if (this.lightning) {
return; return;
} }
@ -77,19 +88,19 @@ export class AddressLabelsComponent implements OnInit {
return; return;
} }
const ops = script.split(' '); const ops = script.split(' ');
if (ops.length < 3 || ops.pop() != 'OP_CHECKMULTISIG') { if (ops.length < 3 || ops.pop() !== 'OP_CHECKMULTISIG') {
return; return;
} }
const opN = ops.pop(); const opN = ops.pop();
if (!opN.startsWith('OP_PUSHNUM_')) { if (!opN.startsWith('OP_PUSHNUM_')) {
return; return;
} }
const n = parseInt(opN.match(/[0-9]+/)[0]); const n = parseInt(opN.match(/[0-9]+/)[0], 10);
if (ops.length < n * 2 + 1) { if (ops.length < n * 2 + 1) {
return; return;
} }
// pop n public keys // pop n public keys
for (var i = 0; i < n; i++) { for (let i = 0; i < n; i++) {
if (!/^0((2|3)\w{64}|4\w{128})$/.test(ops.pop())) { if (!/^0((2|3)\w{64}|4\w{128})$/.test(ops.pop())) {
return; return;
} }
@ -101,13 +112,12 @@ export class AddressLabelsComponent implements OnInit {
if (!opM.startsWith('OP_PUSHNUM_')) { if (!opM.startsWith('OP_PUSHNUM_')) {
return; return;
} }
const m = parseInt(opM.match(/[0-9]+/)[0]); const m = parseInt(opM.match(/[0-9]+/)[0], 10);
this.multisig = true; this.label = `multisig ${m} of ${n}`;
this.multisigM = m;
this.multisigN = n;
} }
handleVout() { handleVout() {
this.detectMultisig(this.vout.scriptpubkey_asm);
} }
} }

View File

@ -155,6 +155,9 @@
<span class="d-block d-lg-none">{{ vout.scriptpubkey_address | shortenString : 16 }}</span> <span class="d-block d-lg-none">{{ vout.scriptpubkey_address | shortenString : 16 }}</span>
<span class="d-none d-lg-block">{{ vout.scriptpubkey_address | shortenString : 35 }}</span> <span class="d-none d-lg-block">{{ vout.scriptpubkey_address | shortenString : 35 }}</span>
</a> </a>
<div>
<app-address-labels [vout]="vout"></app-address-labels>
</div>
<ng-template #scriptpubkey_type> <ng-template #scriptpubkey_type>
<ng-template [ngIf]="vout.pegout" [ngIfElse]="defaultscriptpubkey_type"> <ng-template [ngIf]="vout.pegout" [ngIfElse]="defaultscriptpubkey_type">
<ng-container i18n="transactions-list.peg-out-to">Peg-out to <ng-container *ngTemplateOutlet="pegOutLink"></ng-container></ng-container> <ng-container i18n="transactions-list.peg-out-to">Peg-out to <ng-container *ngTemplateOutlet="pegOutLink"></ng-container></ng-container>