Skip to content

Commit

Permalink
popm/wasm: improve and tidy up Go code (#144)
Browse files Browse the repository at this point in the history
Initial pass to improve and tidy up the Go code for the WASM PoP Miner.

This splits the web/popminer/popminer.go file into 6 files:
 - api.go: Contains all API types
 - dispatch.go: Contains all methods that can be dispatched from JS
 - network.go: Contains Hemi/Bitcoin network settings
 - network_local.go: Contains localnet setting (with build tag)
 - popminer.go: Contains the main function
 - util.go: Contains util functions for interacting with JavaScript

This contains a lot of miscellaneous improvements, however the notable
ones are:
 - Invoke Promise resolve function with `js.Value` instead of marshaled
   JSON, meaning the result can be used directly without the need to
   decode the result as JSON.

 - All errors use a common type, containing 'message', 'timetamp' and
   'stack', allowing for easier debugging and consistency.

 - 'wasmPing' method has been replaced by a 'version' method, which
   returns version information for the PoP miner.

 - All results are now individual Go structs, allowing for more
   consistency and preventing random breakage from changes in other
   packages.

 - Move the network configurations into a separate file and use
   constants. I think this is cleaner than the previous solution, and
   allows localnet to only be available when build with the
   'hemi_localnet' build tag.

 - Move dispatch function to a global object to prevent collisions and
   other issues. The dispatch function is now accessible via a
   `@hemilabs/pop-miner` object.

Reviewed-on: #144
Reviewed-by: Marco Peereboom <[email protected]>
Reviewed-by: ClaytonNorthey92 <[email protected]>
  • Loading branch information
joshuasing authored Jun 17, 2024
1 parent 41a0009 commit a4685a5
Show file tree
Hide file tree
Showing 12 changed files with 1,524 additions and 543 deletions.
2 changes: 1 addition & 1 deletion cmd/popmd/popmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ var (
"POPM_BTC_CHAIN_NAME": config.Config{
Value: &cfg.BTCChainName,
DefaultValue: popm.NewDefaultConfig().BTCChainName,
Help: "the name of the bitcoing chain to connect to (ex. \"mainnet\", \"testnet3\")",
Help: "the name of the bitcoin chain to connect to (ex. \"mainnet\", \"testnet3\")",
Print: config.PrintAll,
},
"POPM_PROMETHEUS_ADDRESS": config.Config{
Expand Down
35 changes: 21 additions & 14 deletions web/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,33 @@
# Use of this source code is governed by the MIT License,
# which can be found in the LICENSE file.

PROJECTPATH = $(abspath $(dir $(realpath $(firstword $(MAKEFILE_LIST)))))

GOROOT=$(shell go env GOROOT)
GITVERSION=$(shell git rev-parse --short HEAD)
WEBAPP=webapp
WEBAPP=$(PROJECTPATH)/webapp
WWW_DIR=$(PROJECTPATH)/www
WASM_BINARY=$(WEBAPP)/popminer.wasm

version = $(patsubst v%,%,$(shell git describe --tags 2>/dev/null || echo "v0.0.0"))
commit = $(shell git rev-parse --short HEAD)

.PHONY: all clean prepare wasm www
.PHONY: all clean wasm www

all: wasm www

clean:
rm -rf ${WEBAPP}
rm -rf ${WASM_BINARY}

prepare:
mkdir -p ${WEBAPP}
# TODO(joshuasing): research using binaryen (wasm-opt) to optimise output binary
wasm:
CGO_ENABLED=0 GOOS=js GOARCH=wasm go build -trimpath -tags "$(BUILD_TAGS)" \
-ldflags "-s -w -X main.version=${version} -X main.gitCommit=${commit}" \
-o ${WASM_BINARY} ${PROJECTPATH}/popminer/...

wasm: prepare
GOOS=js GOARCH=wasm go build -trimpath -ldflags "-X main.gitVersion=${GITVERSION}" \
-o ${WEBAPP}/popminer.wasm ./popminer/popminer.go

www: prepare
cp www/index.html ${WEBAPP}
cp www/index.js ${WEBAPP}
cp www/popminer.js ${WEBAPP}
cp ${GOROOT}/misc/wasm/wasm_exec.js ${WEBAPP}/wasm_exec.js
www: wasm
mkdir -p ${WEBAPP}
cp ${WWW_DIR}/index.html ${WEBAPP}
cp ${WWW_DIR}/index.js ${WEBAPP}
cp ${WWW_DIR}/popminer.js ${WEBAPP}
cp ${WWW_DIR}/wasm_exec.js ${WEBAPP}
150 changes: 150 additions & 0 deletions web/popminer/api.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
// Copyright (c) 2024 Hemi Labs, Inc.
// Use of this source code is governed by the MIT License,
// which can be found in the LICENSE file.

//go:build js && wasm

package main

// Method represents a method that can be dispatched.
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
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
MethodL2Keystones Method = "l2Keystones" // Retrieve L2 keystones
MethodBitcoinBalance Method = "bitcoinBalance" // Retrieve bitcoin balance
MethodBitcoinInfo Method = "bitcoinInfo" // Retrieve bitcoin information
MethodBitcoinUTXOs Method = "bitcoinUTXOs" // Retrieve bitcoin UTXOs
)

// Error represents an error that has occurred within the WASM PoP Miner.
type Error struct {
// Message is the error message.
Message string `json:"message"`

// Stack is the Go debug stack (from debug.Stack()) for the error.
Stack string `json:"stack"`

// Timestamp is the time the error occurred, in unix seconds.
Timestamp int64 `json:"timestamp"`
}

// VersionResult contains version information for the WASM PoP Miner.
// Returned by MethodVersion.
type VersionResult struct {
// Version is the version of the WASM PoP Miner.
Version string `json:"version"`

// GitCommit is the SHA-1 hash of the Git commit the WASM binary was built
// from. The value should be the same as the output from git rev-parse HEAD.
GitCommit string `json:"gitCommit"`
}

// GenerateKeyResult contains the generated key information.
// Returned by MethodGenerateKey.
type GenerateKeyResult struct {
// EthereumAddress is the Ethereum address for the generated key.
EthereumAddress string `json:"ethereumAddress"`

// Network is the network for which the key was generated.
Network string `json:"network"`

// PrivateKey is the generated secpk256k1 private key, encoded as a
// hexadecimal string.
PrivateKey string `json:"privateKey"`

// PublicKey is the generated secp256k1 public key, in the 33-byte
// compressed format, encoded as a hexadecimal string.
PublicKey string `json:"publicKey"`

// PublicKeyHash is the Bitcoin pay-to-pubkey-hash address for the generated
// key.
PublicKeyHash string `json:"publicKeyHash"`
}

// PingResult contains information when pinging the BFG server.
// Returned by MethodPing.
type PingResult struct {
// OriginTimestamp is the time the PoP Miner sent the ping request to BFG,
// in unix nanoseconds.
OriginTimestamp int64 `json:"originTimestamp"`

// Timestamp is the time the BFG server sent the ping response, in unix
// nanoseconds.
Timestamp int64 `json:"timestamp"`
}

// L2KeystoneResult contains the requested l2 keystones.
// Returned by MethodL2Keystones.
type L2KeystoneResult struct {
// L2Keystones contains the requested keystones.
L2Keystones []L2Keystone `json:"l2Keystones"`
}

// L2Keystone represents an L2 keystone.
type L2Keystone struct {
// Version is the version of the L2 keystone.
Version uint8 `json:"version"`

// L1BlockNumber is the L1 block number for the keystone.
L1BlockNumber uint32 `json:"l1BlockNumber"`

// L2BlockNumber is the L2 block number for the keystone.
L2BlockNumber uint32 `json:"l2BlockNumber"`

// EPHash is the hash of the L2 block that contains the PoP payout.
EPHash string `json:"epHash"`

// ParentEPHash is the parent of the L2 block that contains the PoP payout.
ParentEPHash string `json:"parentEPHash"`

// PrevKeystoneEPHash is the hash of the L2 block that contains the previous
// keystone PoP payout.
PrevKeystoneEPHash string `json:"prevKeystoneEPHash"`

// StateRoot is the Ethereum execution payload state root.
StateRoot string `json:"stateRoot"`
}

// BitcoinBalanceResult contains the balances for the script hash.
// Returned by MethodBitcoinBalance.
type BitcoinBalanceResult struct {
// Confirmed is the confirmed balance in satoshis.
Confirmed uint64 `json:"confirmed"`

// Unconfirmed is the unconfirmed balance in satoshis.
Unconfirmed int64 `json:"unconfirmed"`
}

// BitcoinInfoResult contains Bitcoin-related information.
// Returned by MethodBitcoinInfo.
type BitcoinInfoResult struct {
// Height is the current best known Bitcoin block height.
Height uint64 `json:"height"`
}

// BitcoinUTXOsResult contains the UTXOs for the script hash.
// Returned by MethodBitcoinUTXOs.
type BitcoinUTXOsResult struct {
// UTXOs contains the UTXOs for the script hash.
UTXOs []BitcoinUTXO `json:"utxos"`
}

// BitcoinUTXO represents a Bitcoin UTXO.
type BitcoinUTXO struct {
// Hash is the output's transaction hash, encoded as a hexadecimal string.
Hash string `json:"hash"`

// Index is the index of the output in the transaction's list of outputs.
Index uint32 `json:"index"`

// Value is the value of the output in satoshis.
Value int64 `json:"value"`
}
Loading

0 comments on commit a4685a5

Please sign in to comment.