Skip to content
This repository was archived by the owner on May 11, 2021. It is now read-only.

Commit

Permalink
relayer: relay all deposits to latest p2ss address
Browse files Browse the repository at this point in the history
  • Loading branch information
keppel committed Aug 26, 2019
1 parent e30e2b2 commit e23704b
Show file tree
Hide file tree
Showing 6 changed files with 96 additions and 90 deletions.
11 changes: 9 additions & 2 deletions bin/signatory.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,14 @@ let { readFileSync, writeFileSync } = require('fs')
let { randomBytes } = require('crypto')
let { join, dirname } = require('path')
let secp = require('secp256k1')
let { connect } = require('lotion-mock')
let { connect } = require('lotion')
let { commitPubkey, signDisbursal } = require('../dist/src/signatory.js')
let DJSON = require('deterministic-json')

async function main() {
let genesisPath = process.argv[2]
let privValidatorPath = process.argv[3]
let lotionRpcSeed = process.argv[4]

if (genesisPath == null || privValidatorPath == null) {
console.error(
Expand Down Expand Up @@ -45,7 +46,13 @@ async function main() {
)
}

let client = await connect(31338)
let client = await connect(
null,
{
genesis: require(genesisPath),
nodes: [lotionRpcSeed]
}
)
console.log('connected to peg zone network')

// ensure we haven't committed to a key yet
Expand Down
1 change: 0 additions & 1 deletion src/deposit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ export function createBitcoinTx(

// output that pays to the signatory set
let depositOutput = createOutput(validators, signatoryKeys)
console.log(depositOutput)
try {
tx.addOutput(depositOutput, amount)
} catch (e) {
Expand Down
152 changes: 75 additions & 77 deletions src/relay.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,13 @@
import { getSignatoryScriptHashFromPegZone } from './signatory'
import bmp = require('bitcoin-merkle-proof')
let encodeBitcoinTx = require('bitcoin-protocol').types.transaction.encode
let decodeBitcoinTx = require('bitcoin-protocol').types.transaction.decode
let bitcoin = require('bitcoinjs-lib')
let { getTxHash } = require('bitcoin-net/src/utils.js')

interface RelayOptions {
bitcoinRPC: any
lotionLightClient: any
pollIntervalSeconds?: number
/**
* Optionally specify an address to watch for deposits.
*
* If this isn't explicitly provided, it will be derived
* from the signatory keys on the peg zone state.
*/
depositAddress?: string
}

/**
Expand All @@ -29,19 +23,12 @@ interface RelayOptions {
*/
export class Relay {
private bitcoinRPC: any
private pollIntervalSeconds: number = 10
private lotionLightClient: any
private depositAddress?: string

constructor(relayOpts: RelayOptions) {
this.bitcoinRPC = relayOpts.bitcoinRPC
if (relayOpts.pollIntervalSeconds) {
this.pollIntervalSeconds = relayOpts.pollIntervalSeconds
}

this.lotionLightClient = relayOpts.lotionLightClient
if (relayOpts.depositAddress) {
this.depositAddress = relayOpts.depositAddress
}
}
async start() {
let rpc = this.bitcoinRPC
Expand All @@ -54,7 +41,6 @@ export class Relay {
let lastHeader = await rpc.getBlockHeader(lastBlockHash)
let headers = [formatHeader(lastHeader)]
while (lastHeight > startHeight + 1) {
console.log('getting header at height ' + lastHeight)
lastHeader = await rpc.getBlockHeader(lastHeader.previousblockhash)

headers.push(formatHeader(lastHeader))
Expand All @@ -66,7 +52,6 @@ export class Relay {
type: 'bitcoin',
headers: headers.slice(i, i + 100)
})
console.log(result)
}
}
/**
Expand All @@ -77,72 +62,85 @@ export class Relay {
async step() {
let rpc = this.bitcoinRPC
let lc = this.lotionLightClient
// Relay any headers not yet seen by the peg chain.
let pegChainHeaders = await lc.state.bitcoin.chain
console.log('peg chain headers:')
console.log(pegChainHeaders)
let pegChainProcessedTxs = await lc.state.bitcoin.processedTxs
let bestHeaderHeight = (await rpc.getBlockchainInfo()).headers
if (bestHeaderHeight >= pegChainHeaders.length) {
let result = await this.relayHeaders(
pegChainHeaders[pegChainHeaders.length - 1].height
try {
let p2ss = await getSignatoryScriptHashFromPegZone(lc)
let p2ssAddress = bitcoin.payments.p2wsh({
redeem: { output: p2ss },
network: bitcoin.networks.testnet // TODO
}).address
console.log('p2ss address:')
console.log(p2ssAddress)
await rpc.importAddress(
/*address=*/ p2ssAddress,
/*label=*/ '',
/*rescan=*/ false,
/*p2sh=*/ false
)
}
// Check for Bitcoin deposits
// Relay any headers not yet seen by the peg chain.
let pegChainHeaders = await lc.state.bitcoin.chain
let pegChainProcessedTxs = await lc.state.bitcoin.processedTxs
let bestHeaderHeight = (await rpc.getBlockchainInfo()).headers
if (bestHeaderHeight >= pegChainHeaders.length) {
await this.relayHeaders(
pegChainHeaders[pegChainHeaders.length - 1].height
)
}
// Check for Bitcoin deposits

let allReceivedDepositTxs = await rpc.listTransactions('*', 1e9)
console.log('got deposit txs:')
console.log(allReceivedDepositTxs)
let depositsToRelay = allReceivedDepositTxs.filter(
tx =>
tx.address === this.depositAddress &&
tx.category === 'receive' &&
!pegChainProcessedTxs[tx.txid]
)
let pegChainDepositTxs = []
for (let i = 0; i < depositsToRelay.length; i++) {
const VERBOSITY = 2
let depositTx = depositsToRelay[i]
let blockContainingDepositTx = await rpc.getBlock(
depositTx.blockhash,
VERBOSITY
let allReceivedDepositTxs = await rpc.listTransactions('*', 1e9, 0, true)
let depositsToRelay = allReceivedDepositTxs.filter(
tx =>
tx.address === p2ssAddress &&
tx.category === 'receive' &&
typeof tx.blockhash === 'string' &&
!pegChainProcessedTxs[tx.txid]
)
let txHashesInBlock = blockContainingDepositTx.tx.map(tx => {
return Buffer.from(tx.txid, 'hex').reverse()
})
let txHashesInBlockToIncludeInProof = [
Buffer.from(depositTx.txid, 'hex').reverse()
]
let proof = bmp.build({
hashes: txHashesInBlock,
include: txHashesInBlockToIncludeInProof
})
let pegChainDepositTx = {
type: 'bitcoin',
height: blockContainingDepositTx.height,
proof,
transactions: blockContainingDepositTx.tx
.filter(tx => tx.txid === depositTx.txid)
.filter(tx => {
let txid = getTxHash(
decodeBitcoinTx(Buffer.from(tx.hex, 'hex'))
).toString('hex')
let pegChainDepositTxs = []
for (let i = 0; i < depositsToRelay.length; i++) {
const VERBOSITY = 2
let depositTx = depositsToRelay[i]
let blockContainingDepositTx = await rpc.getBlock(
depositTx.blockhash,
VERBOSITY
)
let txHashesInBlock = blockContainingDepositTx.tx.map(tx => {
return Buffer.from(tx.txid, 'hex').reverse()
})
let txHashesInBlockToIncludeInProof = [
Buffer.from(depositTx.txid, 'hex').reverse()
]
let proof = bmp.build({
hashes: txHashesInBlock,
include: txHashesInBlockToIncludeInProof
})
let pegChainDepositTx = {
type: 'bitcoin',
height: blockContainingDepositTx.height,
proof,
transactions: blockContainingDepositTx.tx
.filter(tx => tx.txid === depositTx.txid)
.filter(tx => {
let txid = getTxHash(
decodeBitcoinTx(Buffer.from(tx.hex, 'hex'))
).toString('hex')

return pegChainProcessedTxs[txid] !== true
})
.map(tx => {
return Buffer.from(tx.hex, 'hex')
})
return pegChainProcessedTxs[txid] !== true
})
.map(tx => {
return Buffer.from(tx.hex, 'hex')
})
}
pegChainDepositTxs.push(pegChainDepositTx)
}
pegChainDepositTxs.push(pegChainDepositTx)
}

// Relay deposit transactions to the peg chain
for (let i = 0; i < pegChainDepositTxs.length; i++) {
await lc.send(pegChainDepositTxs[i])
// Relay deposit transactions to the peg chain
for (let i = 0; i < pegChainDepositTxs.length; i++) {
let result = await lc.send(pegChainDepositTxs[i])
}
} catch (e) {
console.log('error during relay:')
console.log(e)
}

// Get current weighted multisig address
}
}

Expand Down
7 changes: 0 additions & 7 deletions src/reserve.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ const MAX_SIGNATORIES = 76
const MIN_RELAY_FEE = 1000

const firstSignatory = signatory => {
console.log(signatory)
return `
${signatory.pubkey} OP_CHECKSIG
OP_IF
Expand Down Expand Up @@ -59,8 +58,6 @@ export function createWitnessScript(
signatoryKeys: SignatoryMap
) {
// get signatory key for each signatory
console.log('getting signatories')
console.log(validators)
let signatories = getSignatorySet(validators)
.map(({ validatorKey, votingPower }) => {
let pubkeyHex
Expand All @@ -72,10 +69,8 @@ export function createWitnessScript(
})
.filter(s => s.pubkey != null)

console.log(signatories)
let twoThirdsVotingPower = getVotingPowerThreshold(signatories)

console.log(signatories)
let asm =
firstSignatory(signatories[0]) +
signatories
Expand All @@ -88,13 +83,11 @@ export function createWitnessScript(
}

export function createScriptSig(signatures) {
console.log(signatures)
let asm = signatures
.map(signature)
.reverse()
.join('\n')

console.log(asm)
return script.fromASM(trim(asm))
}

Expand Down
11 changes: 10 additions & 1 deletion src/signatory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,6 @@ export function buildSignatoryCommitmentTx(
if (signatoryIndex == null) {
throw Error('Given validator key not found in validator set')
}
console.log(signatoryPub)
let signature = ed25519Sign(privValidator, signatoryPub)

return {
Expand Down Expand Up @@ -147,6 +146,16 @@ function ed25519Sign(privValidator: ValidatorKey, message) {
return ed.sign(message, pub, priv)
}

export async function getSignatoryScriptHashFromPegZone(lightClient: any) {
let signatoryKeys = await lightClient.state.bitcoin.signatoryKeys
let lotionValidators = {}
lightClient.validators.forEach((validator: any) => {
lotionValidators[validator.pub_key.value] = validator.voting_power
})
let p2ss = createWitnessScript(lotionValidators, signatoryKeys)
return p2ss
}

// TODO: move this somewhere else
export function convertEd25519(ref10Priv) {
// see https://github.com/orlp/ed25519/issues/10#issuecomment-242761092
Expand Down
4 changes: 2 additions & 2 deletions test/relay.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,8 +108,8 @@ test.skip('header and deposit relaying', async function(t) {
console.log(depositAddress)
let relay = new Relay({
bitcoinRPC: t.context.bitcoind.rpc,
lotionLightClient: lc,
depositAddress
lotionLightClient: lc
// depositAddress
})

await relay.start()
Expand Down

0 comments on commit e23704b

Please sign in to comment.