Skip to content

Commit

Permalink
popm/wasm: add 'bitcoinAddressToScriptHash' method (#169)
Browse files Browse the repository at this point in the history
  • Loading branch information
joshuasing authored Jul 5, 2024
1 parent fe9752a commit 60a3489
Show file tree
Hide file tree
Showing 7 changed files with 144 additions and 5 deletions.
10 changes: 10 additions & 0 deletions web/packages/pop-miner/src/browser/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

import * as types from '../types';
import type {
BitcoinAddressToScriptHashResult,
BitcoinBalanceResult,
BitcoinInfoResult,
BitcoinUTXOsResult,
Expand Down Expand Up @@ -42,6 +43,15 @@ export const parseKey: typeof types.parseKey = ({ network, privateKey }) => {
}) as Promise<KeyResult>;
};

export const bitcoinAddressToScriptHash: typeof types.bitcoinAddressToScriptHash =
({ network, address }) => {
return dispatch({
method: 'bitcoinAddressToScriptHash',
network: network,
address: address,
}) as Promise<BitcoinAddressToScriptHashResult>;
};

export const startPoPMiner: typeof types.startPoPMiner = (args) => {
return dispatchVoid({
method: 'startPoPMiner',
Expand Down
1 change: 1 addition & 0 deletions web/packages/pop-miner/src/browser/wasm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ export type Method =
| 'wasmPing'
| 'generateKey'
| 'parseKey'
| 'bitcoinAddressToScriptHash'
| 'startPoPMiner'
| 'stopPoPMiner'
| 'ping'
Expand Down
44 changes: 44 additions & 0 deletions web/packages/pop-miner/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,50 @@ export type ParseKeyArgs = {
*/
export declare function parseKey(args: ParseKeyArgs): Promise<KeyResult>;

/**
* @see bitcoinAddressToScriptHash
*/
export type BitcoinAddressToScriptHashArgs = {
/**
* Determines the network the key will be parsed for.
*/
network: 'testnet3' | 'mainnet';

/**
* The Bitcoin address to return the script hash of.
*/
address: string;
};

/**
* @see bitcoinAddressToScriptHash
*/
export type BitcoinAddressToScriptHashResult = {
/**
* The network the address is for.
*/
network: 'testnet3' | 'mainnet';

/**
* The address the script hash is for.
*/
address: string;

/**
* The script hash for the address.
*/
scriptHash: string;
};

/**
* Returns the script hash of the given Bitcoin address.
*
* @param args Bitcoin to script hash arguments.
*/
export declare function bitcoinAddressToScriptHash(
args: BitcoinAddressToScriptHashArgs,
): Promise<BitcoinAddressToScriptHashResult>;

/**
* @see startPoPMiner
*/
Expand Down
24 changes: 19 additions & 5 deletions web/popminer/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,12 @@ type Method string

const (
// The following can be dispatched at any time.
MethodVersion Method = "version" // Retrieve WASM version information
MethodGenerateKey Method = "generateKey" // Generate secp256k1 key pair
MethodParseKey Method = "parseKey" // Parses a secp256k1 private and returns key information
MethodStartPoPMiner Method = "startPoPMiner" // Start PoP Miner
MethodStopPoPMiner Method = "stopPoPMiner" // Stop PoP Miner
MethodVersion Method = "version" // Retrieve WASM version information
MethodGenerateKey Method = "generateKey" // Generate secp256k1 key pair
MethodParseKey Method = "parseKey" // Parses a secp256k1 private and returns key information
MethodBitcoinAddressToScriptHash Method = "bitcoinAddressToScriptHash" // Bitcoin address to script hash
MethodStartPoPMiner Method = "startPoPMiner" // Start PoP Miner
MethodStopPoPMiner Method = "stopPoPMiner" // Stop PoP Miner

// The following can only be dispatched after the PoP Miner is running.
MethodPing Method = "ping" // Ping BFG
Expand Down Expand Up @@ -113,6 +114,19 @@ type KeyResult struct {
PublicKeyHash string `json:"publicKeyHash"`
}

// BitcoinAddressToScriptHashResult contains the script hash requested for an
// address.
type BitcoinAddressToScriptHashResult struct {
// Network is the network the address is for.
Network string `json:"network"`

// Address is the address the script hash is for.
Address string `json:"address"`

// ScriptHash is the script hash for the given address.
ScriptHash string `json:"scriptHash"`
}

// PingResult contains information when pinging the BFG server.
// Returned by MethodPing.
type PingResult struct {
Expand Down
38 changes: 38 additions & 0 deletions web/popminer/dispatch.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ package main

import (
"context"
"crypto/sha256"
"encoding/hex"
"errors"
"fmt"
Expand All @@ -17,6 +18,7 @@ import (

"github.com/btcsuite/btcd/btcutil"
btcchaincfg "github.com/btcsuite/btcd/chaincfg"
"github.com/btcsuite/btcd/txscript"
dcrsecp256k1 "github.com/decred/dcrd/dcrec/secp256k1/v4"
"github.com/juju/loggo"

Expand All @@ -42,6 +44,13 @@ var handlers = map[Method]*Dispatch{
{Name: "privateKey", Type: js.TypeString},
},
},
MethodBitcoinAddressToScriptHash: {
Handler: bitcoinAddressToScriptHash,
Required: []DispatchArgs{
{Name: "network", Type: js.TypeString},
{Name: "address", Type: js.TypeString},
},
},
MethodStartPoPMiner: {
Handler: startPoPMiner,
Required: []DispatchArgs{
Expand Down Expand Up @@ -254,6 +263,35 @@ func parseKey(_ js.Value, args []js.Value) (any, error) {
}, nil
}

func bitcoinAddressToScriptHash(_ js.Value, args []js.Value) (any, error) {
log.Tracef("bitcoinAddressToScriptHash")
defer log.Tracef("bitcoinAddressToScriptHash exit")

net, btcChainParams, err := bitcoinNetwork(args[0].Get("network").String())
if err != nil {
return nil, err
}

address := args[0].Get("address").String()
addr, err := btcutil.DecodeAddress(address, btcChainParams)
if err != nil {
return nil, errorWithCode(ErrorCodeInvalidValue,
fmt.Errorf("invalid bitcoin address: %w", err))
}

script, err := txscript.PayToAddrScript(addr)
if err != nil {
return nil, fmt.Errorf("convert address to script: %w", err)
}

scriptHash := sha256.Sum256(script)
return BitcoinAddressToScriptHashResult{
Network: net,
Address: address,
ScriptHash: hex.EncodeToString(scriptHash[:]),
}, nil
}

func bitcoinNetwork(network string) (string, *btcchaincfg.Params, error) {
switch network {
case "devnet", "testnet3", "testnet":
Expand Down
12 changes: 12 additions & 0 deletions web/www/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,18 @@
<pre class="ParseKeyShow"></pre>
</div>

<div>
<input id="BitcoinAddressToScriptHashNetworkInput" value="testnet3">
<label for="BitcoinAddressToScriptHashNetworkInput">bitcoin network</label>
<br>
<input id="BitcoinAddressToScriptHashAddressInput">
<label for="BitcoinAddressToScriptHashAddressInput">bitcoin address</label>
<br>

<button id="BitcoinAddressToScriptHashAddressButton">bitcoin address to script hash</button>
<pre class="BitcoinAddressToScriptHashAddressShow"></pre>
</div>

<div>
<input id="StartPopMinerLogLevelInput" value="hemiwasm=INFO:popm=INFO:protocol=INFO">
<label for="StartPopMinerLogLevelInput">log level</label>
Expand Down
20 changes: 20 additions & 0 deletions web/www/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,26 @@ ParseKeyButton.addEventListener('click', () => {
ParseKey();
});

const BitcoinAddressToScriptHashAddressShow = document.querySelector('.BitcoinAddressToScriptHashAddressShow');

async function BitcoinAddressToScriptHashAddress() {
try {
const result = await dispatch({
method: 'bitcoinAddressToScriptHash',
network: BitcoinAddressToScriptHashNetworkInput.value,
address: BitcoinAddressToScriptHashAddressInput.value,
});
BitcoinAddressToScriptHashAddressShow.innerText = JSON.stringify(result, null, 2);
} catch (err) {
BitcoinAddressToScriptHashAddressShow.innerText = 'Promise rejected: \n' + JSON.stringify(err, null, 2);
console.error('Caught exception', err);
}
}

BitcoinAddressToScriptHashAddressButton.addEventListener('click', () => {
BitcoinAddressToScriptHashAddress();
});

// start pop miner
const StartPopMinerShow = document.querySelector('.StartPopMinerShow');

Expand Down

0 comments on commit 60a3489

Please sign in to comment.