Skip to content
This repository has been archived by the owner on Mar 28, 2023. It is now read-only.

Fetch deposit BTC address (contract code) #25

Merged
merged 37 commits into from
Aug 7, 2019
Merged

Conversation

liamzebedee
Copy link
Contributor

@liamzebedee liamzebedee commented Aug 1, 2019

Refs #14

@liamzebedee liamzebedee marked this pull request as ready for review August 2, 2019 11:16
@nkuba
Copy link
Member

nkuba commented Aug 2, 2019

Shouldn't this PR be linked against #14?

@liamzebedee liamzebedee changed the title Put down small bond (contract code) Fetch deposit BTC address (contract code) Aug 2, 2019
@liamzebedee
Copy link
Contributor Author

This is functioning and ready for review. It just is blocked by #24 being merged, with the artifacts included

Copy link
Member

@nkuba nkuba left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is just a partial implementation of what we need to close #14.

Currently, this PR contains the code to retrieve a public key (from tbtc demo script: https://github.com/keep-network/tbtc/blob/master/implementation/demo/2_fetch_public_key.js).
But we also need to add conversion of the key to the BTC address. More details in #25 (comment).

// 1. Call deposit to create new keep
// 2. Watch for ECDSAKeepCreated event from ECDSAKeepFactory contract
// 3. call get public key
export async function initializeDeposit(depositAddress) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will we need this function? I think we can remove it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep 💯 I think I removed it in #24

}

export async function waitDepositBTCPublicKey(depositAddress) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How do we use this function? I can see that in getDepositBTCPublicKey you're finding RegisteredPubkey event.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should also monitor when the keep is ready with the public key so we can transition from initialize deposit page to retrieve the public key.

I think that for simplification we can just wait for a couple of seconds now (or transition manually on button click) - single signer keep calculates and publishes the key almost immediately.

Later we will need to emit an event from the keep contract and monitor it in the dapp.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah exactly!

So the reason this function is here is to do that. However, due to the current Ganache testchain setup I've got, there's a race between keep-ecdsa emitting the signature and me starting to listen for the event (due to the fact that you can only listen once you have the deposit address).

So to mitigate this, we will have to do some polling instead.


console.log(`Call getPublicKey for deposit [${deposit.address}]`)

let result
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could simplify

  let result
  try {
    result = await deposit.retrieveSignerPubkey()
  } catch(err) {
    console.error(`retrieveSignerPubkey failed: ${err}`)
  }

to

const result = await deposit.retrieveSignerPubkey()
  .catch((err)=> {
    console.error(`retrieveSignerPubkey failed: ${err}`)
  })

const publicKeyX = eventList[0].args._signingGroupPubkeyX
const publicKeyY = eventList[0].args._signingGroupPubkeyY

console.log(`Registered public key:\nX: ${publicKeyX}\nY: ${publicKeyY}`)

return [publicKeyX, publicKeyY]
const address = publicKeyToP2WPKHaddress(
`${publicKeyX.slice(2)}${publicKeyY.slice(2)}`,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the result of ${publicKeyX.slice(2)}${publicKeyY.slice(2)}? Why do we do slice(2)?

We should concatenate X and Y coordinates to 64 bytes. Note that if a coordinate's length is lesser than 32-bytes we should pad it with zeros.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah it's to remove the 0x prefix from the strings :)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe prefer a regex in case you aren't getting the string you expect in the future? Also it's self-documenting :)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Haha I think this miiight be a bit of overkill. Considering it's an event emitted from EVM, the value is uint256, so the string should always be the full length and in the 0x format - these assumptions are validated in the test.

Still tried the regex though ;)

('0x'+'0'.repeat(40)).match(/^(?:0x)([a-fA-F0-9]{40})$/)`

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to add a comment on what's happening and why we slice the values.

Copy link
Contributor Author

@liamzebedee liamzebedee Aug 6, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On second thought, it's not overkill, I couldn't find any docs from Web3 on events.

How's this for self-documenting code!

  let publicKeyX = eventList[0].args._signingGroupPubkeyX
  let publicKeyY = eventList[0].args._signingGroupPubkeyY
  publicKeyX = publicKeyX.replace('0x', '')
  publicKeyY = publicKeyY.replace('0x', '')

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice move!

@liamzebedee
Copy link
Contributor Author

@nkuba also ready for review

@@ -1,6 +1,7 @@
const Web3 = require('web3')

import { createDeposit, setDefaults } from '../src'
import { createDeposit, setDefaults, initializeDeposit, getDepositBTCPublicKey, waitDepositBTCPublicKey } from '../src'
import { setElectrumConfig } from '../src/FundingProof';
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't need this import, right?

Copy link
Contributor Author

@liamzebedee liamzebedee Aug 6, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But I do need that linter! Hahaha

@@ -1,6 +1,7 @@
const Web3 = require('web3')

import { createDeposit, setDefaults } from '../src'
import { createDeposit, setDefaults, initializeDeposit, getDepositBTCPublicKey, waitDepositBTCPublicKey } from '../src'
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need all the functions imported here? It looks to me that we need to add only getDepositBTCPublicKey to the previous imports.

@@ -34,4 +40,68 @@ export async function createDeposit() {
const depositAddress = logs[0].args.depositCloneAddress

return depositAddress
}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove duplicated empty line.

import {
publicKeyToP2WPKHaddress,
Network
} from '../../lib/tbtc-helpers/src/Address'
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this be } from 'tbtc-helpers/src/Address'? We have tbtc-helpers as a package dependency.

}


// A complement to getDepositBTCPublicKey.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Update to JS docs style we use in other functions.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So if we're not using it maybe we shouldn't commit it? Will we use it for the demo dapp?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@nkuba I'd prefer not to throw away the code if it's going to be useful in immediate future. 😄

In this case (and I know I keep saying this), we are building a library out of the client/ package. As I explained in the comment, the purpose of this function, while not needed yet, will be needed in the production environment.

I would write a test for the function too, so that it's not just dangling there in the code...?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A good practice is to write a code for immediate future but mainnet is not that immediate. Experience shows that such a code is usually dangling, after a month or two, nobody knows why it's there, it gets out of date quickly and it is maintained only to have the compilation passing with no effort in understanding what it really does.

If we were to use this code in a week or two, this would be fine to leave it, but if it's a matter of months, I'd propose to ☠️ it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok in which case I'll remove it.

* @param {string} depositAddress the address of a Deposit contract
* @returns a bech32-encoded Bitcoin address
*/
export async function getDepositBTCPublicKey(depositAddress) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The name getDepositBTCPublicKey is not accurate. We're getting the BTC address from this function.

We already have a function for this purpose in:

async function getAddress(depositAddress) {

Can we move the implementation to the function I linked?
Actually getBTCadress name would be better than getAddress.
It's up to you if we keep it in Deposit.js or FundingTransaction.js file.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep 100% agree - will do.

export async function getDepositBTCPublicKey(depositAddress) {
const tbtcSystem = await TBTCSystem.deployed()

// 1. Request it from the deposit
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's be more specific and replace it/this in comments with public key and others.

})

// 2. Parse the logs to get it
// we can't get this from result.logs, since it's emitted in another contract
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's more, we should do it as we do here (with fromBlock: '0') because retrieveSignerPubkey might fail because the key was already retrieved (see my previous comment). Let's have it in a comment.


console.log(`Registered public key for deposit ${depositAddress}:\nX: ${publicKeyX}\nY: ${publicKeyY}`)

const address = publicKeyToP2WPKHaddress(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

address -> btcAddress

@nkuba
Copy link
Member

nkuba commented Aug 6, 2019

Let's edit this PR and set base branch to master. We also need to reverse merge master to this branch.

@nkuba
Copy link
Member

nkuba commented Aug 6, 2019

Re: artifacts - I'd prefer to check them in now and remove later? Even though they'll fail due to missing deployments - at least it won't break the build (since they're being require'd).

We will upload the artifacts deployed on our internal testnet in #35. Let's don't commit them in this PR.

@liamzebedee
Copy link
Contributor Author

Ready @nkuba

@nkuba
Copy link
Member

nkuba commented Aug 6, 2019

Let's merge master to this branch and see if CI passes.

// TODO: Implement:
// 1. Get keep public key from the deposit
// 2. Calculate P2WPKH address from the key

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So many blank lines, let's remove them in one of the upcoming PRs.

}


Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here about blank lines.

package.json Outdated
@@ -16,6 +16,7 @@
"redux": "^4.0.4",
"redux-saga": "^1.0.5",
"tbtc-client": "file:client",
"tbtc-helpers": "file:lib/tbtc-helpers",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need this dependency in dapp's package.json? We should be using only tbtc-client.

@@ -1,12 +1,61 @@
const Address = require('tbtc-helpers').Address
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CI is failing because of this removal.

@nkuba nkuba force-pushed the put-down-small-bond branch from d2d1845 to 030b620 Compare August 6, 2019 15:44
@pdyraga
Copy link
Member

pdyraga commented Aug 6, 2019

Failed to compile.

./lib/tbtc-helpers/node_modules/bcoin/lib/bcoin.js
Critical dependency: the request of a dependency is an expression

./lib/tbtc-helpers/node_modules/bcoin/node_modules/bcrypto/lib/node/bn.js
SyntaxError: /home/circleci/project/lib/tbtc-helpers/node_modules/bcoin/node_modules/bcrypto/lib/node/bn.js: Identifier directly after number (51:17)

  49 |  */
  50 | 
> 51 | const U8_MAX = (1n << 8n) - 1n;
     |                  ^
  52 | const U16_MAX = (1n << 16n) - 1n;
  53 | const U32_MAX = (1n << 32n) - 1n;
  54 | const U64_MAX = (1n << 64n) - 1n;

./lib/tbtc-helpers/node_modules/bcrypto/lib/node/bn.js
SyntaxError: /home/circleci/project/lib/tbtc-helpers/node_modules/bcrypto/lib/node/bn.js: Identifier directly after number (46:17)

  44 |  */
  45 | 
> 46 | const U8_MAX = (1n << 8n) - 1n;
     |                  ^
  47 | const U16_MAX = (1n << 16n) - 1n;
  48 | const U32_MAX = (1n << 32n) - 1n;
  49 | const U64_MAX = (1n << 64n) - 1n;

@liamzebedee
Copy link
Contributor Author

Yeah @pdyraga see this thread

@nkuba nkuba merged commit 8690899 into master Aug 7, 2019
@nkuba nkuba deleted the put-down-small-bond branch August 7, 2019 19:34
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants