Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bifrost - alpha version #81

Merged
merged 24 commits into from
Dec 5, 2017
Merged

Bifrost - alpha version #81

merged 24 commits into from
Dec 5, 2017

Conversation

bartekn
Copy link
Contributor

@bartekn bartekn commented Oct 2, 2017

Demo app
https://bifrost.stellar.org/

  1. First you need some ETH on Ethereum testnet.
  2. Create an account at https://www.myetherwallet.com/, then switch Network (top-right dropdown) to "Ropsten (MyEtherWallet)". Write down/copy your Ethereum address somewhere.
  3. Use http://faucet.ropsten.be:3001/ to send 3 ETH to your testnet account.
  4. Now open Bifrost demo: https://bifrost.stellar.org/ It will display address where to send your test ETH.
  5. Go back to MyEtherWallet and send ETH to the address displayed by Bifrost. Sometimes Ropsten network is overloaded so monitor the Etherscan if you tx was included in a block. If not, increated gas price (this can be done in "Send Offline" tab).
  6. Switch back to Bifrost demo and check the progress.

Work in progress: do not use in production, do not merge.

This is MVP version of Bifrost [design doc]. Bifrost accepts coins from other blockchains and issues them on Stellar blockchain.

TODO (random order):

Copy link
Contributor

@poliha poliha left a comment

Choose a reason for hiding this comment

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

Looks good in general. Just had my first glance over it, will continue to read the code and I guess we will improve on it as we fix issues.
Quick question is setting blocknumber to 0 in BTC/ETH equivalent to setting cursor to "now" in stellar?


var checkKeysCmd = &cobra.Command{
Use: "check-keys",
Short: "Displays a few public keys derivied using master public keys",
Copy link
Contributor

Choose a reason for hiding this comment

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

typo derived

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks!

Use: "version",
Short: "Print the version number",
Run: func(cmd *cobra.Command, args []string) {
fmt.Println("version")
Copy link
Contributor

Choose a reason for hiding this comment

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

Version number is not printed

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, tracking in #158

}

ethereumListener.Enabled = true
ethereumListener.NetworkID = "3"
Copy link
Contributor

Choose a reason for hiding this comment

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

Should the NetworkID be from the config file? In case the user wants to use a different test network?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This code is responsible for stress tests so it should always be testnet.

TxOutIndex: index,
ValueSat: output.Value,
To: addresses[0].EncodeAddress(),
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Not sure about this, but I think addresses can be more than one. This only picks the first address

Copy link
Contributor Author

Choose a reason for hiding this comment

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

There can be more than one address for multisig outputs. Bifrost receiving addresses are normal P2PKH addresses so always only one address.

@@ -0,0 +1,440 @@
package database
Copy link
Contributor

Choose a reason for hiding this comment

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

Can these functions also be used when we implement support for another DB type?
If so maybe we shouldn't just name this postgres.go? or maybe move it into main.go?
What do you think here?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I don't think there are plans to use other DB engines.

// the transactions queue for StellarAccountConfigurator to consume.
//
// Transaction added to transactions queue should be in a format described in
// queue.Queue (especialy amounts). Pooling service should not have to deal with any
Copy link
Contributor

Choose a reason for hiding this comment

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

I think this should be queue.Transaction? Also check ethereum_rail.go

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks!

// entry with the same ID was added.
// This is a critical requirement! Otherwise ETH/BTC may be sent twice to Stellar account.
// If you don't know what to do, use default AWS SQS FIFO queue or DB queue.
type Queue interface {
Copy link
Contributor

Choose a reason for hiding this comment

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

Question, has this been implemented?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, Database implementation Queue works as expected. No implementation for SQS FIFO yet but it's not urgent as we have DB one.

@bartekn
Copy link
Contributor Author

bartekn commented Nov 14, 2017

Quick question is setting blocknumber to 0 in BTC/ETH equivalent to setting cursor to "now" in stellar?

Exactly.

Copy link
Contributor

@nikhilsaraf nikhilsaraf left a comment

Choose a reason for hiding this comment

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

Added first pass of comments, most of them are code style comments.
Will go more in depth into reviewing the architecture and other parts in the next pass.


## Going to production

* Remember than everyone with master public key and **any** child private key can recover your **master** private key. Do not share your master public key and obviously any private keys. Treat your master public key as if it was a private key. Read more in BIP-0032 [Security](https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki#security) section.
Copy link
Contributor

Choose a reason for hiding this comment

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

type? (Remember than -> Remember that)

## Going to production

* Remember than everyone with master public key and **any** child private key can recover your **master** private key. Do not share your master public key and obviously any private keys. Treat your master public key as if it was a private key. Read more in BIP-0032 [Security](https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki#security) section.
* Make sure "Sell [your token] for BTC" and/or "Sell [your token] for ETH" exist in Stellar production network.
Copy link
Contributor

Choose a reason for hiding this comment

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

can you provide more information about what this "Sell [your token] for BTC/Ethereum" means (purpose, where to find it, is this referring to a mange offer)?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

In the last stage of the flow BTC/ETH tokens will be exchanged to [your token] on SDEX. Yes, it's manage_offer.

Copy link
Contributor

Choose a reason for hiding this comment

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

I think we should update this to reflect that the manage_offer should exist. I completely misinterpreted this to expect that I should look for that text somewhere.

* It's a good idea to set "Authorization required" and "Authorization revocable" [flags](https://www.stellar.org/developers/guides/concepts/accounts.html#flags) on issuing account during ICO stage to remove trustlines to accounts with lost keys.
* Monitor bifrost logs and react to all WARN and ERROR entries.
* Make sure you are using geth >= 1.7.1 and bitcoin-core >= 0.15.0.
* Turn off horizon rate limiting.
Copy link
Contributor

Choose a reason for hiding this comment

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

can you add a reason for why they should turn off rate limiting? (shouldn't it be on to help prevent any DDOS attacks?)

* Make sure you are using geth >= 1.7.1 and bitcoin-core >= 0.15.0.
* Turn off horizon rate limiting.
* Make sure you configured minimum accepted value for Bitcoin and Ethereum transactions to the value you really want.
* Make sure you start from a fresh DB in production. If Bifrost was running, you stopped it and then started again all the block mined during that that will be processed what can take a lot of time.
Copy link
Contributor

Choose a reason for hiding this comment

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

does blocks mining refer to bitcoin blocks here?
If they start from a fresh db in production then will it not try to catchup to the bitcoin network anyways?

typo? (If Bifrost was running, you stopped it bitcoin-core and then started it again then all the blocks mined during that that time will be processed what which can take a lot of time.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

does blocks mining refer to bitcoin blocks here?

Bitcoin and Ethereum.

If they start from a fresh db in production then will it not try to catchup to the bitcoin network anyways?

I meant Bifrost DB. The Bitcoin and Ethereum nodes should stay in sync all the time. Will fix this.


[database]
type="postgres"
dsn="postgres://bartek@localhost/bifrost?sslmode=disable"
Copy link
Contributor

Choose a reason for hiding this comment

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

should we remove sslmode=disable here to encourage encrypted db connections?

logger := log.DefaultLogger

if serviceName != "" {
logger = logger.WithField("service", serviceName)
Copy link
Contributor

Choose a reason for hiding this comment

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

why save in logger, could just return here and then always return log.DefaultLogger below instead of creating above.

pooled boolean NOT NULL DEFAULT false,
PRIMARY KEY (id),
UNIQUE (transaction_id, asset_code),
CONSTRAINT valid_asset_code CHECK (char_length(asset_code) >= 3),
Copy link
Contributor

Choose a reason for hiding this comment

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

can we not have an asset_code that is less then 3 characters long?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Currently we only support BTC and ETH. We will update this CHECK if there is new asset with less or more than 3 chars. Changed >= to =.

return nil
}

func (l *Listener) processBlocks(blockNumber uint64) {
Copy link
Contributor

Choose a reason for hiding this comment

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

this function seems common between btc and ethereum implementation. Can we extract this into it's own component that takes in the logInterval (20 minutes vs. 3 minutes), logIntervalString (string representation of logInterval), and Storage? -- see comment in Storage for interface change suggestion to support this extraction


// Storage is an interface that must be implemented by an object using
// persistent storage.
type Storage interface {
Copy link
Contributor

Choose a reason for hiding this comment

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

this interface is serving the same purpose as that of the bitcoin Storage. They can both be the same interface by generalizing the method names on this interface and we can have one BitcoinStorage implementation and another EthereumStorage implementation. Will make it possible to then extract the logic in processBlocks up above.

Copy link
Contributor

Choose a reason for hiding this comment

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

We should address this issue since there's a fair amount of code duplication going on here via copy-paste, which can make code maintenance a lot more costly later on.

masterPublicKey *bip32.Key
}

func EthToWei(eth string) (*big.Int, error) {
Copy link
Contributor

Choose a reason for hiding this comment

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

this is also common, can extract to an object that takes in the multiplier (weiInEth or satInBtc) and also unitName (satoshi / wei) for the error message.

@bartekn bartekn changed the title [WIP] Bifrost Bifrost - alpha version Dec 5, 2017
@bartekn
Copy link
Contributor Author

bartekn commented Dec 5, 2017

I think the code is good for Alpha version for developers and community to test. @nikhilsaraf can you approve?

nikhilsaraf
nikhilsaraf previously approved these changes Dec 5, 2017
Copy link
Contributor

@nikhilsaraf nikhilsaraf left a comment

Choose a reason for hiding this comment

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

Approving as an alpha version to let the ball roll on this and to not be a blocker since this has already been used in production and we should get it out asap.

Please address some of the leftover comments (particularly design comments) when you get back to this code.

return db, err
}

func createServer(cfg config.Config, stressTest bool) *server.Server {
Copy link
Contributor

Choose a reason for hiding this comment

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

this function is very long, for the next change, can you break it up? -- maybe split up the for loop blocks into their own functions.

Short: "Starts stress test",
Long: `During stress test bitcoin and ethereum transaction will be generated randomly.
This command will create 3 server.Server's listening on ports 8000-8002.`,
Run: func(cmd *cobra.Command, args []string) {
Copy link
Contributor

Choose a reason for hiding this comment

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

here too, could split up this function and move to it's own named function rather than inline since it's quite large

@@ -0,0 +1,399 @@
// Skip this file in Go <1.8 because it's using http.Server.Shutdown
Copy link
Contributor

Choose a reason for hiding this comment

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

why is the architecture.png image here? -- I thought it was only for the design doc?

@bartekn bartekn merged commit da7a365 into master Dec 5, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants