diff --git a/README.md b/README.md index 99cdc501d..c3cb84e26 100644 --- a/README.md +++ b/README.md @@ -107,7 +107,7 @@ $ bazel build //sharding/... Make sure a geth node is running as a separate process. Then, to deposit ETH and join as a notary in the Sharding Manager Contract, run the following command: ``` -$ bazel run //sharding --actor "notary" --deposit --datadir /path/to/your/datadir --password /path/to/your/password.txt --networkid 12345 +$ ./bazel-bin/path/to/your/sharding/binary --actor "notary" --deposit --datadir /path/to/your/datadir --password /path/to/your/password.txt --networkid 12345 ``` This will extract 1000ETH from your account balance and insert you into the SMC's notaries. Then, the program will listen for incoming block headers and notify you when you have been selected as to vote on proposals for a certain shard in a given period. Once you are selected, your sharding node will download collation information to check for data availability on vote on proposals that have been submitted via the `addHeader` function on the SMC. @@ -117,14 +117,14 @@ Concurrently, you will need to run another service that is tasked with processin ## Running a Collation Proposal Node ``` -$ bazel run //sharding --actor "proposer" --datadir /path/to/your/datadir --password /path/to/your/password.txt --shardid 0 --networkid 12345 +$ ./bazel-bin/path/to/your/sharding/binary --actor "proposer" --datadir /path/to/your/datadir --password /path/to/your/password.txt --shardid 0 --networkid 12345 ``` This node is tasked with processing pending transactions into blobs within collations by serializing data into collation bodies. It is responsible for submitting proposals on shard 0 (collation headers) to the SMC via the `addHeader` function. ## Running an Observer Node - $ bazel run //sharding --datadir /path/to/your/datadir --password /path/to/your/password.txt --shardid 0 --networkid 12345 + $ ./bazel-bin/path/to/your/sharding/binary --datadir /path/to/your/datadir --password /path/to/your/password.txt --shardid 0 --networkid 12345 Omitting the `--actor` flag will launch a simple observer service attached to the sharding client that is able to listen to changes happening throughout the sharded Ethereum network on shard 0. diff --git a/WORKSPACE b/WORKSPACE index 379b08b47..487a780ac 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -48,6 +48,336 @@ go_repository( commit = "ca190fb6ffbc076ff49197b7168a760f30182d2e", ) +go_repository( + name = "com_github_libp2p_go_floodsub", + commit = "1b4fbb865d4944a602b27e24e8123a57095e9987", + importpath = "github.com/libp2p/go-floodsub", +) + +go_repository( + name = "com_github_libp2p_go_libp2p", + commit = "934606d0f292f265eab890101233d18ffeabfda0", + importpath = "github.com/libp2p/go-libp2p", +) + +go_repository( + name = "com_github_libp2p_go_libp2p_peer", + commit = "a26c4b782bfe3b2570c539f69dc7777a45117a90", + importpath = "github.com/libp2p/go-libp2p-peer", +) + +go_repository( + name = "com_github_libp2p_go_libp2p_crypto", + commit = "18915b5467c77ad8c07a35328c2cab468667a4e8", + importpath = "github.com/libp2p/go-libp2p-crypto", +) + +go_repository( + name = "com_github_multiformats_go_multiaddr", + commit = "96804982667ed1672985566d0d0c2a7ed6f10e1f", + importpath = "github.com/multiformats/go-multiaddr", +) + +go_repository( + name = "com_github_ipfs_go_log", + commit = "5dc2060baaf8db344f31dafd852340b93811d03f", + importpath = "github.com/ipfs/go-log", +) + +go_repository( + name = "com_github_multiformats_go_multihash", + commit = "8be2a682ab9f254311de1375145a2f78a809b07d", + importpath = "github.com/multiformats/go-multihash", +) + +go_repository( + name = "com_github_libp2p_go_libp2p_swarm", + commit = "81c57653cf47f106c6779a17a1e24ce192a0a42d", + importpath = "github.com/libp2p/go-libp2p-swarm", +) + +go_repository( + name = "com_github_libp2p_go_libp2p_host", + commit = "c2196843b63fc9da2999045ca7fbae64e53b6461", + importpath = "github.com/libp2p/go-libp2p-host", +) + +go_repository( + name = "com_github_libp2p_go_libp2p_peerstore", + commit = "49898a5f59ac4bea31b49d0c62ba214a6da16dbd", + importpath = "github.com/libp2p/go-libp2p-peerstore", +) + +go_repository( + name = "com_github_libp2p_go_libp2p_circuit", + commit = "ee6dd9116af74cc17c03a199c258817543b0704b", + importpath = "github.com/libp2p/go-libp2p-circuit", +) + +go_repository( + name = "com_github_coreos_go_semver", + commit = "e214231b295a8ea9479f11b70b35d5acf3556d9b", + importpath = "github.com/coreos/go-semver", +) + +go_repository( + name = "com_github_libp2p_go_libp2p_interface_connmgr", + commit = "ba1fa6b3d7aed40798c930634ba109bcd7b879d9", + importpath = "github.com/libp2p/go-libp2p-interface-connmgr", +) + +go_repository( + name = "com_github_libp2p_go_conn_security_multistream", + commit = "df26ef91ad66a626a4b7147fd95d18962395a20e", + importpath = "github.com/libp2p/go-conn-security-multistream", +) + +go_repository( + name = "com_github_libp2p_go_libp2p_metrics", + commit = "c51c712333790bf9318c6d02b2e0129c239b5d65", + importpath = "github.com/libp2p/go-libp2p-metrics", +) + +go_repository( + name = "com_github_libp2p_go_libp2p_net", + commit = "d387f776809c666d02d69953e860be9f5bad5640", + importpath = "github.com/libp2p/go-libp2p-net", +) + +go_repository( + name = "com_github_whyrusleeping_mafmt", + commit = "1dc32401ee9fdd3f6cdb3405ec984d5dae877b2a", + importpath = "github.com/whyrusleeping/mafmt", +) + +go_repository( + name = "com_github_multiformats_go_multiaddr_net", + commit = "cba4f9fea8613343eb7ecc4ddadd8e7298a00c39", + importpath = "github.com/multiformats/go-multiaddr-net", +) + +go_repository( + name = "com_github_agl_ed25519", + commit = "5312a61534124124185d41f09206b9fef1d88403", + importpath = "github.com/agl/ed25519", +) + +go_repository( + name = "com_github_minio_blake2b_simd", + commit = "3f5f724cb5b182a5c278d6d3d55b40e7f8c2efb4", + importpath = "github.com/minio/blake2b-simd", +) + +go_repository( + name = "com_github_gxed_hashland", + commit = "d9f6b97f8db22dd1e090fd0bbbe98f09cc7dd0a8", + importpath = "github.com/gxed/hashland", +) + +go_repository( + name = "com_github_mattn_go_colorable", + commit = "efa589957cd060542a26d2dd7832fd6a6c6c3ade", + importpath = "github.com/mattn/go-colorable", +) + +go_repository( + name = "com_github_whyrusleeping_mdns", + commit = "348bb87e5cd39b33dba9a33cb20802111e5ee029", + importpath = "github.com/whyrusleeping/mdns", +) + +go_repository( + name = "com_github_btcsuite_btcd", + commit = "fdfc19097e7ac6b57035062056f5b7b4638b8898", + importpath = "github.com/btcsuite/btcd", +) + +go_repository( + name = "com_github_minio_sha256_simd", + commit = "ad98a36ba0da87206e3378c556abbfeaeaa98668", + importpath = "github.com/minio/sha256-simd", +) + +go_repository( + name = "com_github_mr_tron_base58", + commit = "4df4dc6e86a912614d09719d10cad427b087cbfb", + importpath = "github.com/mr-tron/base58", +) + +go_repository( + name = "com_github_whyrusleeping_go_smux_yamux", + commit = "eac25f3e2d47aae211e457e7664b52634c95eea8", + importpath = "github.com/whyrusleeping/go-smux-yamux", +) + +go_repository( + name = "com_github_libp2p_go_libp2p_secio", + commit = "6cb371175c430ef0d98ed06c0b1de4df275a2b2d", + importpath = "github.com/libp2p/go-libp2p-secio", +) + +go_repository( + name = "com_github_libp2p_go_tcp_transport", + commit = "d8cd27e09a919868bf2a9bbe144453b974a35b3f", + importpath = "github.com/libp2p/go-tcp-transport", +) + +go_repository( + name = "com_github_libp2p_go_libp2p_protocol", + commit = "b29f3d97e3a2fb8b29c5d04290e6cb5c5018004b", + importpath = "github.com/libp2p/go-libp2p-protocol", +) + +go_repository( + name = "com_github_jbenet_goprocess", + commit = "b497e2f366b8624394fb2e89c10ab607bebdde0b", + importpath = "github.com/jbenet/goprocess", +) + +go_repository( + name = "com_github_multiformats_go_multistream", + commit = "aea59cd120a7f60ed64cc98ffc1af2e6a84c470f", + importpath = "github.com/multiformats/go-multistream", +) + +go_repository( + name = "com_github_libp2p_go_libp2p_loggables", + commit = "825bdca6800792bf8013c54670072023f58f2770", + importpath = "github.com/libp2p/go-libp2p-loggables", +) + +go_repository( + name = "com_github_libp2p_go_libp2p_nat", + commit = "b2342fe96714ea4535cd80706967f7deab0706e9", + importpath = "github.com/libp2p/go-libp2p-nat", +) + +go_repository( + name = "com_github_multiformats_go_multiaddr_dns", + commit = "78f39e8892d4f8c5c9f18679cc06d0b40ecab8cf", + importpath = "github.com/multiformats/go-multiaddr-dns", +) + +go_repository( + name = "com_github_fd_go_nat", + commit = "bad65a492f32121a87197f4a085905c35e2a367e", + importpath = "github.com/fd/go-nat", +) + +go_repository( + name = "com_github_whyrusleeping_go_logging", + commit = "0457bb6b88fc1973573aaf6b5145d8d3ae972390", + importpath = "github.com/whyrusleeping/go-logging", +) + +go_repository( + name = "com_github_mattn_go_isatty", + commit = "6ca4dbf54d38eea1a992b3c722a76a5d1c4cb25c", + importpath = "github.com/mattn/go-isatty", +) + +go_repository( + name = "com_github_libp2p_go_stream_muxer", + commit = "9c6bd93eecbbab56630bb2688bb435d9fd1dfeb1", + importpath = "github.com/libp2p/go-stream-muxer", +) + +go_repository( + name = "com_github_libp2p_go_libp2p_transport_upgrader", + commit = "baf347fe2d1b8d138a9eccaebfacbb8d45f565ff", + importpath = "github.com/libp2p/go-libp2p-transport-upgrader", +) + +go_repository( + name = "com_github_libp2p_go_testutil", + commit = "f967bbd5fcb7fb6337504e5d78c53c865e80733c", + importpath = "github.com/libp2p/go-testutil", +) + +go_repository( + name = "com_github_whyrusleeping_go_smux_multistream", + commit = "c707bf3c25fa380b20b54907790efde288775938", + importpath = "github.com/whyrusleeping/go-smux-multistream", +) + +go_repository( + name = "com_github_libp2p_go_maddr_filter", + commit = "57fd7e2ed649ba28b4f2c7bcab3a606e7cc4b12c", + importpath = "github.com/libp2p/go-maddr-filter", +) + +go_repository( + name = "com_github_libp2p_go_libp2p_transport", + commit = "52a99afeb515360b51a5e357fedc925b2dcb1deb", + importpath = "github.com/libp2p/go-libp2p-transport", +) + +go_repository( + name = "com_github_libp2p_go_addr_util", + commit = "56c6a7f748424cab4ff68da653ff01363e3cd745", + importpath = "github.com/libp2p/go-addr-util", +) + +go_repository( + name = "com_github_libp2p_go_libp2p_interface_pnet", + commit = "86e6fc84b906599eac696308369896ece0ced63b", + importpath = "github.com/libp2p/go-libp2p-interface-pnet", +) + +go_repository( + name = "com_github_libp2p_go_conn_security", + commit = "1f43a64c9d5d3796daca8d9e9dd2f2001272a706", + importpath = "github.com/libp2p/go-conn-security", +) + +go_repository( + name = "com_github_whyrusleeping_timecache", + commit = "cfcb2f1abfee846c430233aef0b630a946e0a5a6", + importpath = "github.com/whyrusleeping/timecache", +) + +go_repository( + name = "com_github_miekg_dns", + commit = "3e6e47bc11bc7f93f9e2f1c7bd6481ba4802808b", + importpath = "github.com/miekg/dns", +) + +go_repository( + name = "com_github_opentracing_opentracing_go", + commit = "bd9c3193394760d98b2fa6ebb2291f0cd1d06a7d", + importpath = "github.com/opentracing/opentracing-go", +) + +go_repository( + name = "com_github_libp2p_go_reuseport", + commit = "c2c3368efe65c8b85ddff6b278df5bef3ce235e2", + importpath = "github.com/libp2p/go-reuseport", +) + +go_repository( + name = "com_github_huin_goupnp", + commit = "1395d1447324cbea88d249fbfcfd70ea878fdfca", + importpath = "github.com/huin/goupnp", +) + +go_repository( + name = "com_github_spaolacci_murmur3", + commit = "f09979ecbc725b9e6d41a297405f65e7e8804acc", + importpath = "github.com/spaolacci/murmur3", +) + +go_repository( + name = "com_github_jbenet_go_temp_err_catcher", + commit = "aac704a3f4f27190b4ccc05f303a4931fd1241ff", + importpath = "github.com/jbenet/go-temp-err-catcher", +) + +go_repository( + name = "com_github_satori_go_uuid", + commit = "36e9d2ebbde5e3f13ab2e25625fd453271d6522e", + importpath = "github.com/satori/go.uuid", +) + go_repository( name = "com_github_sirupsen_logrus", importpath = "github.com/sirupsen/logrus", @@ -56,16 +386,106 @@ go_repository( go_repository( name = "org_golang_x_sys", - commit = "1b2967e3c290b7c545b3db0deeda16e9be4f98a2", + commit = "3c6ecd8f22c6f40fbeec94c000a069d7d87c7624", importpath = "golang.org/x/sys", ) +go_repository( + name = "com_github_whyrusleeping_yamux", + commit = "35d045d4429ecf19430a2b94efc590bc40f2f7af", + importpath = "github.com/whyrusleeping/yamux", +) + +go_repository( + name = "com_github_libp2p_go_flow_metrics", + commit = "3b3bcfcf78f2dc0e85be13ef3c3adc64cc5a9347", + importpath = "github.com/libp2p/go-flow-metrics", +) + +go_repository( + name = "com_github_libp2p_go_msgio", + commit = "d82125c9907e1365775356505f14277d47dfd4d6", + importpath = "github.com/libp2p/go-msgio", +) + +go_repository( + name = "com_github_jackpal_gateway", + commit = "cbcf4e3f3baee7952fc386c8b2534af4d267c875", + importpath = "github.com/jackpal/gateway", +) + +go_repository( + name = "com_github_whyrusleeping_multiaddr_filter", + commit = "e903e4adabd70b78bc9293b6ee4f359afb3f9f59", + importpath = "github.com/whyrusleeping/multiaddr-filter", +) + +go_repository( + name = "com_github_libp2p_go_ws_transport", + commit = "0c9c253a870ece2182843290e616b8c103abb9c6", + importpath = "github.com/libp2p/go-ws-transport", +) + go_repository( name = "org_golang_x_crypto", commit = "a49355c7e3f8fe157a85be2f77e6e269a0f89602", importpath = "golang.org/x/crypto", ) +go_repository( + name = "com_github_jackpal_go_nat_pmp", + commit = "28a68d0c24adce1da43f8df6a57340909ecd7fdd", + importpath = "github.com/jackpal/go-nat-pmp", +) + +go_repository( + name = "com_github_libp2p_go_reuseport_transport", + commit = "3165117d78404111af975e3e9af2b54dd46f0819", + importpath = "github.com/libp2p/go-reuseport-transport", +) + +go_repository( + name = "com_github_libp2p_go_sockaddr", + commit = "3c898fbfff40e5933d76362819727708dae6da97", + importpath = "github.com/libp2p/go-sockaddr", +) + +go_repository( + name = "com_github_whyrusleeping_go_notifier", + commit = "097c5d47330ff6a823f67e3515faa13566a62c6f", + importpath = "github.com/whyrusleeping/go-notifier", +) + +go_repository( + name = "com_github_gorilla_websocket", + commit = "5ed622c449da6d44c3c8329331ff47a9e5844f71", + importpath = "github.com/gorilla/websocket", +) + +go_repository( + name = "com_github_whyrusleeping_go_smux_multiplex", + commit = "121cd99ce58b0b5a36d9630e3f673bce4733ac6f", + importpath = "github.com/whyrusleeping/go-smux-multiplex", +) + +go_repository( + name = "com_github_gxed_eventfd", + commit = "80a92cca79a8041496ccc9dd773fcb52a57ec6f9", + importpath = "github.com/gxed/eventfd", +) + +go_repository( + name = "com_github_whyrusleeping_go_multiplex", + commit = "015295179194cbcc2eb7e13504222749af868544", + importpath = "github.com/whyrusleeping/go-multiplex", +) + +go_repository( + name = "com_github_gxed_goendian", + commit = "0f5c6873267e5abf306ffcdfcfa4bf77517ef4a7", + importpath = "github.com/gxed/GoEndian", +) + go_repository( name = "com_github_syndtr_goleveldb", commit = "c4c61651e9e37fa117f53c5a906d3b63090d8445", diff --git a/contracts/deployVRC/BUILD.bazel b/contracts/deployVRC/BUILD.bazel new file mode 100644 index 000000000..1be809e9c --- /dev/null +++ b/contracts/deployVRC/BUILD.bazel @@ -0,0 +1,24 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library") + +go_library( + name = "go_default_library", + srcs = ["deployVRC.go"], + importpath = "github.com/prysmaticlabs/geth-sharding/contracts/deployVRC", + visibility = ["//visibility:private"], + deps = [ + "//contracts:go_default_library", + "@com_github_ethereum_go_ethereum//accounts/abi/bind:go_default_library", + "@com_github_ethereum_go_ethereum//accounts/keystore:go_default_library", + "@com_github_ethereum_go_ethereum//crypto:go_default_library", + "@com_github_ethereum_go_ethereum//ethclient:go_default_library", + "@com_github_ethereum_go_ethereum//rpc:go_default_library", + "@com_github_sirupsen_logrus//:go_default_library", + "@com_github_urfave_cli//:go_default_library", + ], +) + +go_binary( + name = "deployVRC", + embed = [":go_default_library"], + visibility = ["//visibility:public"], +) diff --git a/contracts/deployVRC/README.md b/contracts/deployVRC/README.md new file mode 100644 index 000000000..ace3ca881 --- /dev/null +++ b/contracts/deployVRC/README.md @@ -0,0 +1,45 @@ +## Utility to Deploy Validator Registraction Contract + +This is a utility to help users deploy validator registration contract for running their own beacon chain node in a local containerized set up. To run the utility, it assumes there is a running geth node as a separate process attached to proof-of-work main chain. The utility will deploy the validator registration contract and print out the contract address. Users will pass the contract address to the beacon chain node to monitor when they have been conducted to become an active validator. + +### Usage + +*Name:* + **deployVRC** - this is a util to deploy validator registration contract + +*Usage:* + deployVRC [global options] command [command options] [arguments...] + +*Flags:* + **--keystoreUTCPath** Keystore UTC file to unlock account (default: "./datadir/keystore/UTC...") + **--ipcPath** Filename for IPC socket/pipe within the datadir (default: "./geth.ipc") + **--httpPath** HTTP-RPC server listening interface (default: "http://localhost:8545/") + **--passwordFile** Password file for unlock account (default: "./password.txt") + **--privKey** Private key to unlock account + **--help, -h** show help + **--version, -v** print the version + +### Example +To use private key with default RPC: +``` +bazel run //deployVRC --privKey yourPrivateKey +``` + +To use UTC JSON with IPC: +``` +bazel run //deployVRC --ipcPath /path/to/your/geth.ipc --UTCPath /path/to/your/keystore/UTCJSON --passwordFile /path/to/your/password.txt +``` +To use UTC JSON with RPC: +``` +bazel run //deployVRC --httpPath http://localhost:8545/ --UTCPath /path/to/your/keystore/UTCJSON --passwordFile /path/to/your/password.txt +``` +or +``` +bazel run //deployVRC --UTCPath /path/to/your/keystore/UTCJSON --passwordFile /path/to/your/password.txt + +``` + +### Output +``` +INFO[0001] New contract deployed at 0x5275C2220C574330E230bFB7e4a0b96f60a18f02 +``` diff --git a/contracts/deployVRC/deployVRC.go b/contracts/deployVRC/deployVRC.go new file mode 100644 index 000000000..e6c7ad352 --- /dev/null +++ b/contracts/deployVRC/deployVRC.go @@ -0,0 +1,131 @@ +package main + +import ( + "bufio" + "context" + "io/ioutil" + "math/big" + "os" + "time" + + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/accounts/keystore" + "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/ethclient" + "github.com/ethereum/go-ethereum/rpc" + "github.com/prysmaticlabs/geth-sharding/contracts" + log "github.com/sirupsen/logrus" + "github.com/urfave/cli" +) + +func main() { + var keystoreUTCPath string + var ipcPath string + var passwordFile string + var httpPath string + var privKeyString string + + app := cli.NewApp() + app.Name = "deployVRC" + app.Usage = "this is a util to deploy validator registration contract" + app.Flags = []cli.Flag{ + cli.StringFlag{ + Name: "keystoreUTCPath", + Usage: "Location of keystore", + Destination: &keystoreUTCPath, + }, + cli.StringFlag{ + Name: "ipcPath", + Usage: "Filename for IPC socket/pipe within the datadir", + Destination: &ipcPath, + }, + cli.StringFlag{ + Name: "httpPath", + Value: "http://localhost:8545/", + Usage: "HTTP-RPC server listening interface", + Destination: &httpPath, + }, + cli.StringFlag{ + Name: "passwordFile", + Value: "./password.txt", + Usage: "Password file for unlock account", + Destination: &passwordFile, + }, + cli.StringFlag{ + Name: "privKey", + Usage: "Private key to unlock account", + Destination: &privKeyString, + }, + } + + app.Action = func(c *cli.Context) { + // Set up RPC client + var rpcClient *rpc.Client + var err error + var txOps *bind.TransactOpts + + // Uses HTTP-RPC if IPC is not set + if ipcPath == "" { + rpcClient, err = rpc.Dial(httpPath) + } else { + rpcClient, err = rpc.Dial(ipcPath) + } + if err != nil { + log.Fatal(err) + } + + client := ethclient.NewClient(rpcClient) + + // User inputs private key, sign tx with private key + if privKeyString != "" { + privKey, err := crypto.HexToECDSA(privKeyString) + if err != nil { + log.Fatal(err) + } + txOps = bind.NewKeyedTransactor(privKey) + txOps.Value = big.NewInt(0) + + // User inputs keystore json file, sign tx with keystore json + } else { + file, err := os.Open(passwordFile) + if err != nil { + log.Fatal(err) + } + + scanner := bufio.NewScanner(file) + scanner.Split(bufio.ScanWords) + scanner.Scan() + password := scanner.Text() + + keyJSON, _ := ioutil.ReadFile(keystoreUTCPath) + privKey, err := keystore.DecryptKey(keyJSON, password) + if err != nil { + log.Fatal(err) + } + + txOps = bind.NewKeyedTransactor(privKey.PrivateKey) + txOps.Value = big.NewInt(0) + } + + // Deploy validator registration contract + addr, tx, _, err := contracts.DeployValidatorRegistration(txOps, client) + if err != nil { + log.Fatal(err) + } + + // Wait for contract to mine + for pending := true; pending; _, pending, err = client.TransactionByHash(context.Background(), tx.Hash()) { + if err != nil { + log.Fatal(err) + } + time.Sleep(1 * time.Second) + } + + log.Infof("New contract deployed at %s", addr.Hex()) + } + + err := app.Run(os.Args) + if err != nil { + log.Fatal(err) + } +} diff --git a/contracts/validator_registration.go b/contracts/validator_registration.go index b87471fc7..1a5b600f1 100644 --- a/contracts/validator_registration.go +++ b/contracts/validator_registration.go @@ -19,7 +19,7 @@ import ( const ValidatorRegistrationABI = "[{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"usedPubkey\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"VALIDATOR_DEPOSIT\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_pubkey\",\"type\":\"bytes32\"},{\"name\":\"_withdrawalShardID\",\"type\":\"uint256\"},{\"name\":\"_withdrawalAddressbytes32\",\"type\":\"address\"},{\"name\":\"_randaoCommitment\",\"type\":\"bytes32\"}],\"name\":\"deposit\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"pubKey\",\"type\":\"bytes32\"},{\"indexed\":false,\"name\":\"withdrawalShardID\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"withdrawalAddressbytes32\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"randaoCommitment\",\"type\":\"bytes32\"}],\"name\":\"ValidatorRegistered\",\"type\":\"event\"}]" // ValidatorRegistrationBin is the compiled bytecode used for deploying new contracts. -const ValidatorRegistrationBin = `0x608060405234801561001057600080fd5b506101d3806100206000396000f3006080604052600436106100565763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166301110845811461005b578063441d92cc14610087578063881d2135146100ae575b600080fd5b34801561006757600080fd5b506100736004356100da565b604080519115158252519081900360200190f35b34801561009357600080fd5b5061009c6100ef565b60408051918252519081900360200190f35b6100d860043560243573ffffffffffffffffffffffffffffffffffffffff604435166064356100fc565b005b60006020819052908152604090205460ff1681565b6801bc16d674ec80000081565b346801bc16d674ec8000001461011157600080fd5b60008481526020819052604090205460ff161561012d57600080fd5b60008481526020818152604091829020805460ff19166001179055815186815290810185905273ffffffffffffffffffffffffffffffffffffffff8416818301526060810183905290517f7b0678aab009b61a805f5004869728b53a444f9a3e6bb9e22b8537c89af512749181900360800190a1505050505600a165627a7a72305820ba933a3e2d7a01de483490b3379e3c0ff9eb8040d0bb6eccf192fca140f752d70029` +const ValidatorRegistrationBin = `0x608060405234801561001057600080fd5b506101d3806100206000396000f3006080604052600436106100565763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166301110845811461005b578063441d92cc14610087578063881d2135146100ae575b600080fd5b34801561006757600080fd5b506100736004356100da565b604080519115158252519081900360200190f35b34801561009357600080fd5b5061009c6100ef565b60408051918252519081900360200190f35b6100d860043560243573ffffffffffffffffffffffffffffffffffffffff604435166064356100fc565b005b60006020819052908152604090205460ff1681565b6801bc16d674ec80000081565b346801bc16d674ec8000001461011157600080fd5b60008481526020819052604090205460ff161561012d57600080fd5b60008481526020818152604091829020805460ff19166001179055815186815290810185905273ffffffffffffffffffffffffffffffffffffffff8416818301526060810183905290517f7b0678aab009b61a805f5004869728b53a444f9a3e6bb9e22b8537c89af512749181900360800190a1505050505600a165627a7a7230582030b51cf5829c9fac611cd2060acc062996b9cc9cf3d57d32b2b54c509a32b85d0029` // DeployValidatorRegistration deploys a new Ethereum contract, binding an instance of ValidatorRegistration to it. func DeployValidatorRegistration(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *ValidatorRegistration, error) { diff --git a/proto/sharding/v1/BUILD.bazel b/proto/sharding/v1/BUILD.bazel new file mode 100644 index 000000000..74dd84b0c --- /dev/null +++ b/proto/sharding/v1/BUILD.bazel @@ -0,0 +1,28 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library") +load("@io_bazel_rules_go//proto:def.bzl", "go_proto_library") + +proto_library( + name = "messages_proto", + srcs = ["messages.proto"], + visibility = ["//visibility:public"], +) + +go_proto_library( + name = "messages_go_proto", + importpath = "github.com/prysmaticlabs/geth-sharding/proto/sharding/v1", + proto = ":ethereum_messages_v1_proto", + visibility = ["//visibility:public"], +) + +go_library( + name = "go_default_library", + embed = [":messages_go_proto"], + importpath = "github.com/prysmaticlabs/geth-sharding/proto/sharding/v1", + visibility = ["//visibility:public"], +) + +proto_library( + name = "ethereum_messages_v1_proto", + srcs = ["messages.proto"], + visibility = ["//visibility:public"], +) diff --git a/proto/sharding/v1/messages.pb.go b/proto/sharding/v1/messages.pb.go new file mode 100644 index 000000000..7ef3079ff --- /dev/null +++ b/proto/sharding/v1/messages.pb.go @@ -0,0 +1,346 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// source: messages.proto + +package ethereum_messages_v1 + +import proto "github.com/golang/protobuf/proto" +import fmt "fmt" +import math "math" + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package + +type Topic int32 + +const ( + Topic_UNKNOWN Topic = 0 + Topic_COLLATION_BODY_REQUEST Topic = 1 + Topic_COLLATION_BODY_RESPONSE Topic = 2 + Topic_TRANSACTIONS Topic = 3 +) + +var Topic_name = map[int32]string{ + 0: "UNKNOWN", + 1: "COLLATION_BODY_REQUEST", + 2: "COLLATION_BODY_RESPONSE", + 3: "TRANSACTIONS", +} +var Topic_value = map[string]int32{ + "UNKNOWN": 0, + "COLLATION_BODY_REQUEST": 1, + "COLLATION_BODY_RESPONSE": 2, + "TRANSACTIONS": 3, +} + +func (x Topic) String() string { + return proto.EnumName(Topic_name, int32(x)) +} +func (Topic) EnumDescriptor() ([]byte, []int) { + return fileDescriptor_messages_b2b448a5e8345e4f, []int{0} +} + +type CollationBodyRequest struct { + ShardId uint64 `protobuf:"varint,1,opt,name=shard_id,json=shardId,proto3" json:"shard_id,omitempty"` + Period uint64 `protobuf:"varint,2,opt,name=period,proto3" json:"period,omitempty"` + ChunkRoot []byte `protobuf:"bytes,3,opt,name=chunk_root,json=chunkRoot,proto3" json:"chunk_root,omitempty"` + ProposerAddress []byte `protobuf:"bytes,4,opt,name=proposer_address,json=proposerAddress,proto3" json:"proposer_address,omitempty"` + Signature []byte `protobuf:"bytes,5,opt,name=signature,proto3" json:"signature,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *CollationBodyRequest) Reset() { *m = CollationBodyRequest{} } +func (m *CollationBodyRequest) String() string { return proto.CompactTextString(m) } +func (*CollationBodyRequest) ProtoMessage() {} +func (*CollationBodyRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_messages_b2b448a5e8345e4f, []int{0} +} +func (m *CollationBodyRequest) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_CollationBodyRequest.Unmarshal(m, b) +} +func (m *CollationBodyRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_CollationBodyRequest.Marshal(b, m, deterministic) +} +func (dst *CollationBodyRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_CollationBodyRequest.Merge(dst, src) +} +func (m *CollationBodyRequest) XXX_Size() int { + return xxx_messageInfo_CollationBodyRequest.Size(m) +} +func (m *CollationBodyRequest) XXX_DiscardUnknown() { + xxx_messageInfo_CollationBodyRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_CollationBodyRequest proto.InternalMessageInfo + +func (m *CollationBodyRequest) GetShardId() uint64 { + if m != nil { + return m.ShardId + } + return 0 +} + +func (m *CollationBodyRequest) GetPeriod() uint64 { + if m != nil { + return m.Period + } + return 0 +} + +func (m *CollationBodyRequest) GetChunkRoot() []byte { + if m != nil { + return m.ChunkRoot + } + return nil +} + +func (m *CollationBodyRequest) GetProposerAddress() []byte { + if m != nil { + return m.ProposerAddress + } + return nil +} + +func (m *CollationBodyRequest) GetSignature() []byte { + if m != nil { + return m.Signature + } + return nil +} + +type CollationBodyResponse struct { + HeaderHash []byte `protobuf:"bytes,1,opt,name=header_hash,json=headerHash,proto3" json:"header_hash,omitempty"` + Body []byte `protobuf:"bytes,2,opt,name=body,proto3" json:"body,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *CollationBodyResponse) Reset() { *m = CollationBodyResponse{} } +func (m *CollationBodyResponse) String() string { return proto.CompactTextString(m) } +func (*CollationBodyResponse) ProtoMessage() {} +func (*CollationBodyResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_messages_b2b448a5e8345e4f, []int{1} +} +func (m *CollationBodyResponse) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_CollationBodyResponse.Unmarshal(m, b) +} +func (m *CollationBodyResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_CollationBodyResponse.Marshal(b, m, deterministic) +} +func (dst *CollationBodyResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_CollationBodyResponse.Merge(dst, src) +} +func (m *CollationBodyResponse) XXX_Size() int { + return xxx_messageInfo_CollationBodyResponse.Size(m) +} +func (m *CollationBodyResponse) XXX_DiscardUnknown() { + xxx_messageInfo_CollationBodyResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_CollationBodyResponse proto.InternalMessageInfo + +func (m *CollationBodyResponse) GetHeaderHash() []byte { + if m != nil { + return m.HeaderHash + } + return nil +} + +func (m *CollationBodyResponse) GetBody() []byte { + if m != nil { + return m.Body + } + return nil +} + +type Transaction struct { + Nonce uint64 `protobuf:"varint,1,opt,name=nonce,proto3" json:"nonce,omitempty"` + GasPrice uint64 `protobuf:"varint,2,opt,name=gas_price,json=gasPrice,proto3" json:"gas_price,omitempty"` + GasLimit uint64 `protobuf:"varint,3,opt,name=gas_limit,json=gasLimit,proto3" json:"gas_limit,omitempty"` + Recipient []byte `protobuf:"bytes,4,opt,name=recipient,proto3" json:"recipient,omitempty"` + Value uint64 `protobuf:"varint,5,opt,name=value,proto3" json:"value,omitempty"` + Input []byte `protobuf:"bytes,6,opt,name=input,proto3" json:"input,omitempty"` + Signature *Signture `protobuf:"bytes,7,opt,name=signature,proto3" json:"signature,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *Transaction) Reset() { *m = Transaction{} } +func (m *Transaction) String() string { return proto.CompactTextString(m) } +func (*Transaction) ProtoMessage() {} +func (*Transaction) Descriptor() ([]byte, []int) { + return fileDescriptor_messages_b2b448a5e8345e4f, []int{2} +} +func (m *Transaction) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_Transaction.Unmarshal(m, b) +} +func (m *Transaction) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_Transaction.Marshal(b, m, deterministic) +} +func (dst *Transaction) XXX_Merge(src proto.Message) { + xxx_messageInfo_Transaction.Merge(dst, src) +} +func (m *Transaction) XXX_Size() int { + return xxx_messageInfo_Transaction.Size(m) +} +func (m *Transaction) XXX_DiscardUnknown() { + xxx_messageInfo_Transaction.DiscardUnknown(m) +} + +var xxx_messageInfo_Transaction proto.InternalMessageInfo + +func (m *Transaction) GetNonce() uint64 { + if m != nil { + return m.Nonce + } + return 0 +} + +func (m *Transaction) GetGasPrice() uint64 { + if m != nil { + return m.GasPrice + } + return 0 +} + +func (m *Transaction) GetGasLimit() uint64 { + if m != nil { + return m.GasLimit + } + return 0 +} + +func (m *Transaction) GetRecipient() []byte { + if m != nil { + return m.Recipient + } + return nil +} + +func (m *Transaction) GetValue() uint64 { + if m != nil { + return m.Value + } + return 0 +} + +func (m *Transaction) GetInput() []byte { + if m != nil { + return m.Input + } + return nil +} + +func (m *Transaction) GetSignature() *Signture { + if m != nil { + return m.Signature + } + return nil +} + +type Signture struct { + V uint64 `protobuf:"varint,1,opt,name=v,proto3" json:"v,omitempty"` + R uint64 `protobuf:"varint,2,opt,name=r,proto3" json:"r,omitempty"` + S uint64 `protobuf:"varint,3,opt,name=s,proto3" json:"s,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *Signture) Reset() { *m = Signture{} } +func (m *Signture) String() string { return proto.CompactTextString(m) } +func (*Signture) ProtoMessage() {} +func (*Signture) Descriptor() ([]byte, []int) { + return fileDescriptor_messages_b2b448a5e8345e4f, []int{3} +} +func (m *Signture) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_Signture.Unmarshal(m, b) +} +func (m *Signture) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_Signture.Marshal(b, m, deterministic) +} +func (dst *Signture) XXX_Merge(src proto.Message) { + xxx_messageInfo_Signture.Merge(dst, src) +} +func (m *Signture) XXX_Size() int { + return xxx_messageInfo_Signture.Size(m) +} +func (m *Signture) XXX_DiscardUnknown() { + xxx_messageInfo_Signture.DiscardUnknown(m) +} + +var xxx_messageInfo_Signture proto.InternalMessageInfo + +func (m *Signture) GetV() uint64 { + if m != nil { + return m.V + } + return 0 +} + +func (m *Signture) GetR() uint64 { + if m != nil { + return m.R + } + return 0 +} + +func (m *Signture) GetS() uint64 { + if m != nil { + return m.S + } + return 0 +} + +func init() { + proto.RegisterType((*CollationBodyRequest)(nil), "ethereum.messages.v1.CollationBodyRequest") + proto.RegisterType((*CollationBodyResponse)(nil), "ethereum.messages.v1.CollationBodyResponse") + proto.RegisterType((*Transaction)(nil), "ethereum.messages.v1.Transaction") + proto.RegisterType((*Signture)(nil), "ethereum.messages.v1.Signture") + proto.RegisterEnum("ethereum.messages.v1.Topic", Topic_name, Topic_value) +} + +func init() { proto.RegisterFile("messages.proto", fileDescriptor_messages_b2b448a5e8345e4f) } + +var fileDescriptor_messages_b2b448a5e8345e4f = []byte{ + // 445 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x6c, 0x92, 0xcd, 0x6e, 0xd3, 0x4c, + 0x14, 0x86, 0xbf, 0x69, 0xf3, 0x7b, 0x62, 0x7d, 0x58, 0xa3, 0x50, 0x0c, 0xe5, 0x27, 0xca, 0x2a, + 0xb0, 0x88, 0xc4, 0xcf, 0x92, 0x4d, 0x1a, 0x22, 0x51, 0x11, 0xd9, 0xc5, 0x76, 0x85, 0x58, 0x59, + 0x53, 0xfb, 0xc8, 0x1e, 0x91, 0xcc, 0x98, 0x39, 0x76, 0xa4, 0x5e, 0x16, 0x17, 0xc5, 0x7d, 0xa0, + 0xb1, 0x9d, 0x52, 0x01, 0x3b, 0x3f, 0xef, 0x7b, 0x34, 0x3e, 0xcf, 0xd8, 0xf0, 0xff, 0x1e, 0x89, + 0x44, 0x8e, 0xb4, 0x2c, 0x8d, 0xae, 0x34, 0x9f, 0x62, 0x55, 0xa0, 0xc1, 0x7a, 0xbf, 0xbc, 0x2b, + 0x0e, 0xaf, 0xe7, 0x3f, 0x18, 0x4c, 0xd7, 0x7a, 0xb7, 0x13, 0x95, 0xd4, 0xea, 0x42, 0x67, 0xb7, + 0x21, 0x7e, 0xaf, 0x91, 0x2a, 0xfe, 0x18, 0x46, 0x54, 0x08, 0x93, 0x25, 0x32, 0xf3, 0xd8, 0x8c, + 0x2d, 0x7a, 0xe1, 0xb0, 0xe1, 0xcb, 0x8c, 0x9f, 0xc1, 0xa0, 0x44, 0x23, 0x75, 0xe6, 0x9d, 0x34, + 0x45, 0x47, 0xfc, 0x19, 0x40, 0x5a, 0xd4, 0xea, 0x5b, 0x62, 0xb4, 0xae, 0xbc, 0xd3, 0x19, 0x5b, + 0x38, 0xe1, 0xb8, 0x49, 0x42, 0xad, 0x2b, 0xfe, 0x12, 0xdc, 0xd2, 0xe8, 0x52, 0x13, 0x9a, 0x44, + 0x64, 0x99, 0x41, 0x22, 0xaf, 0xd7, 0x0c, 0x3d, 0x38, 0xe6, 0xab, 0x36, 0xe6, 0x4f, 0x61, 0x4c, + 0x32, 0x57, 0xa2, 0xaa, 0x0d, 0x7a, 0xfd, 0xf6, 0xa0, 0xbb, 0x60, 0xbe, 0x85, 0x87, 0x7f, 0xac, + 0x4c, 0xa5, 0x56, 0x84, 0xfc, 0x05, 0x4c, 0x0a, 0x14, 0x19, 0x9a, 0xa4, 0x10, 0x54, 0x34, 0x6b, + 0x3b, 0x21, 0xb4, 0xd1, 0x47, 0x41, 0x05, 0xe7, 0xd0, 0xbb, 0xd1, 0xd9, 0x6d, 0xb3, 0xb7, 0x13, + 0x36, 0xcf, 0xf3, 0x9f, 0x0c, 0x26, 0xb1, 0x11, 0x8a, 0x44, 0x6a, 0x0f, 0xe4, 0x53, 0xe8, 0x2b, + 0xad, 0x52, 0xec, 0xac, 0x5b, 0xe0, 0xe7, 0x30, 0xce, 0x05, 0x25, 0xa5, 0x91, 0x29, 0x76, 0xda, + 0xa3, 0x5c, 0xd0, 0x95, 0xe5, 0x63, 0xb9, 0x93, 0x7b, 0xd9, 0x7a, 0xb7, 0xe5, 0xd6, 0xb2, 0x75, + 0x31, 0x98, 0xca, 0x52, 0xa2, 0xaa, 0x3a, 0xdf, 0xdf, 0x81, 0x7d, 0xdb, 0x41, 0xec, 0xea, 0xd6, + 0xb2, 0x17, 0xb6, 0x60, 0x53, 0xa9, 0xca, 0xba, 0xf2, 0x06, 0xcd, 0x7c, 0x0b, 0xfc, 0xfd, 0xfd, + 0x5b, 0x19, 0xce, 0xd8, 0x62, 0xf2, 0xe6, 0xf9, 0xf2, 0x5f, 0x5f, 0x75, 0x19, 0xc9, 0x5c, 0xd9, + 0xa9, 0xfb, 0xb7, 0xf6, 0x0e, 0x46, 0xc7, 0x98, 0x3b, 0xc0, 0x0e, 0x9d, 0x1f, 0x3b, 0x58, 0x32, + 0x9d, 0x13, 0x33, 0x96, 0xa8, 0x93, 0x60, 0xf4, 0x2a, 0x81, 0x7e, 0xac, 0x4b, 0x99, 0xf2, 0x09, + 0x0c, 0xaf, 0xfd, 0x4f, 0x7e, 0xf0, 0xc5, 0x77, 0xff, 0xe3, 0x4f, 0xe0, 0x6c, 0x1d, 0x6c, 0xb7, + 0xab, 0xf8, 0x32, 0xf0, 0x93, 0x8b, 0xe0, 0xc3, 0xd7, 0x24, 0xdc, 0x7c, 0xbe, 0xde, 0x44, 0xb1, + 0xcb, 0xf8, 0x39, 0x3c, 0xfa, 0xab, 0x8b, 0xae, 0x02, 0x3f, 0xda, 0xb8, 0x27, 0xdc, 0x05, 0x27, + 0x0e, 0x57, 0x7e, 0xb4, 0x5a, 0xdb, 0x3a, 0x72, 0x4f, 0x6f, 0x06, 0xcd, 0xdf, 0xf9, 0xf6, 0x57, + 0x00, 0x00, 0x00, 0xff, 0xff, 0x27, 0xa7, 0xf1, 0x57, 0xaf, 0x02, 0x00, 0x00, +} diff --git a/proto/sharding/v1/messages.proto b/proto/sharding/v1/messages.proto new file mode 100644 index 000000000..5ed449174 --- /dev/null +++ b/proto/sharding/v1/messages.proto @@ -0,0 +1,39 @@ +syntax = "proto3"; + +package ethereum.messages.v1; + +enum Topic { + UNKNOWN = 0; + COLLATION_BODY_REQUEST = 1; + COLLATION_BODY_RESPONSE = 2; + TRANSACTIONS = 3; +} + +message CollationBodyRequest { + uint64 shard_id = 1; + uint64 period = 2; + bytes chunk_root = 3; + bytes proposer_address = 4; + bytes signature = 5; +} + +message CollationBodyResponse { + bytes header_hash = 1; + bytes body = 2; +} + +message Transaction { + uint64 nonce = 1; + uint64 gas_price = 2; + uint64 gas_limit = 3; + bytes recipient = 4; + uint64 value = 5; + bytes input = 6; + Signture signature = 7; +} + +message Signture { + uint64 v = 1; + uint64 r = 2; + uint64 s = 3; +} diff --git a/sharding/main.go b/sharding/main.go index 54cbed89c..7cb6bf302 100644 --- a/sharding/main.go +++ b/sharding/main.go @@ -16,7 +16,7 @@ func startNode(ctx *cli.Context) error { if err != nil { return err } - // starts a connection to a beacon node and kicks off every registered service. + shardingNode.Start() return nil } diff --git a/sharding/notary/BUILD.bazel b/sharding/notary/BUILD.bazel index 915868909..1c0ad7f61 100644 --- a/sharding/notary/BUILD.bazel +++ b/sharding/notary/BUILD.bazel @@ -24,6 +24,7 @@ go_library( go_test( name = "go_default_test", + size = "medium", srcs = ["service_test.go"], embed = [":go_default_library"], deps = [ diff --git a/sharding/p2p/BUILD.bazel b/sharding/p2p/BUILD.bazel index 5d720cdad..0f4830f5b 100644 --- a/sharding/p2p/BUILD.bazel +++ b/sharding/p2p/BUILD.bazel @@ -3,15 +3,28 @@ load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") go_library( name = "go_default_library", srcs = [ + "discovery.go", "feed.go", "message.go", + "options.go", "peer.go", "service.go", + "topics.go", ], importpath = "github.com/prysmaticlabs/geth-sharding/sharding/p2p", visibility = ["//sharding:__subpackages__"], deps = [ + "//proto/sharding/v1:go_default_library", "@com_github_ethereum_go_ethereum//event:go_default_library", + "@com_github_golang_protobuf//proto:go_default_library", + "@com_github_libp2p_go_floodsub//:go_default_library", + "@com_github_libp2p_go_libp2p//:go_default_library", + "@com_github_libp2p_go_libp2p//p2p/discovery:go_default_library", + "@com_github_libp2p_go_libp2p_crypto//:go_default_library", + "@com_github_libp2p_go_libp2p_host//:go_default_library", + "@com_github_libp2p_go_libp2p_peer//:go_default_library", + "@com_github_libp2p_go_libp2p_peerstore//:go_default_library", + "@com_github_multiformats_go_multiaddr//:go_default_library", "@com_github_sirupsen_logrus//:go_default_library", ], ) @@ -19,10 +32,25 @@ go_library( go_test( name = "go_default_test", srcs = [ + "discovery_test.go", "feed_example_test.go", "feed_test.go", + "options_test.go", "service_test.go", + "topics_test.go", ], embed = [":go_default_library"], - deps = ["//sharding/types:go_default_library"], + deps = [ + "//proto/sharding/v1:go_default_library", + "//sharding/types:go_default_library", + "@com_github_ethereum_go_ethereum//event:go_default_library", + "@com_github_golang_protobuf//proto:go_default_library", + "@com_github_libp2p_go_floodsub//:go_default_library", + "@com_github_libp2p_go_libp2p//p2p/discovery:go_default_library", + "@com_github_libp2p_go_libp2p//p2p/host/basic:go_default_library", + "@com_github_libp2p_go_libp2p_peer//:go_default_library", + "@com_github_libp2p_go_libp2p_swarm//testing:go_default_library", + "@com_github_sirupsen_logrus//:go_default_library", + "@com_github_sirupsen_logrus//hooks/test:go_default_library", + ], ) diff --git a/sharding/p2p/discovery.go b/sharding/p2p/discovery.go new file mode 100644 index 000000000..fd074f82f --- /dev/null +++ b/sharding/p2p/discovery.go @@ -0,0 +1,71 @@ +package p2p + +import ( + "context" + "time" + + host "github.com/libp2p/go-libp2p-host" + peer "github.com/libp2p/go-libp2p-peer" + ps "github.com/libp2p/go-libp2p-peerstore" + mdns "github.com/libp2p/go-libp2p/p2p/discovery" + pb "github.com/prysmaticlabs/geth-sharding/proto/sharding/v1" + log "github.com/sirupsen/logrus" +) + +// Discovery interval for multicast DNS querying. +var discoveryInterval = 1 * time.Minute + +// mDNSTag is the name of the mDNS service. +var mDNSTag = mdns.ServiceTag + +// startDiscovery protocols. Currently, this supports discovery via multicast +// DNS peer discovery. +// +// TODO: add other discovery protocols such as DHT, etc. +func startDiscovery(ctx context.Context, host host.Host, gsub topicPeerLister) error { + mdnsService, err := mdns.NewMdnsService(ctx, host, discoveryInterval, mDNSTag) + if err != nil { + return err + } + + mdnsService.RegisterNotifee(&discovery{ctx, host, gsub}) + + return nil +} + +// topicPeerLister has a method to return connected peers on a given topic. +// This is implemented by floodsub.PubSub. +type topicPeerLister interface { + ListPeers(string) []peer.ID +} + +// Discovery implements mDNS notifee interface. +type discovery struct { + ctx context.Context + host host.Host + + // Required for helper method. + gsub topicPeerLister +} + +// HandlePeerFound registers the peer with the host. +func (d *discovery) HandlePeerFound(pi ps.PeerInfo) { + d.host.Peerstore().AddAddrs(pi.ID, pi.Addrs, ps.PermanentAddrTTL) + if err := d.host.Connect(d.ctx, pi); err != nil { + log.Warnf("Failed to connect to peer: %v", err) + } + + log.Debugf("Peers now: %s", d.host.Peerstore().Peers()) + log.Debugf("gsub has peers: %v", d.topicPeerMap()) +} + +// topicPeerMap helper function for inspecting which peers are available for +// the p2p topics. +func (d *discovery) topicPeerMap() map[pb.Topic][]peer.ID { + m := make(map[pb.Topic][]peer.ID) + for topic := range topicTypeMapping { + peers := d.gsub.ListPeers(topic.String()) + m[topic] = peers + } + return m +} diff --git a/sharding/p2p/discovery_test.go b/sharding/p2p/discovery_test.go new file mode 100644 index 000000000..cb9b1b594 --- /dev/null +++ b/sharding/p2p/discovery_test.go @@ -0,0 +1,64 @@ +package p2p + +import ( + "context" + "testing" + "time" + + floodsub "github.com/libp2p/go-floodsub" + peer "github.com/libp2p/go-libp2p-peer" + swarmt "github.com/libp2p/go-libp2p-swarm/testing" + mdns "github.com/libp2p/go-libp2p/p2p/discovery" + bhost "github.com/libp2p/go-libp2p/p2p/host/basic" +) + +var _ = mdns.Notifee(&discovery{}) +var _ = topicPeerLister(&floodsub.PubSub{}) + +var _ = topicPeerLister(&fakeTopicPeerLister{}) + +type fakeTopicPeerLister struct { +} + +func (f *fakeTopicPeerLister) ListPeers(topic string) []peer.ID { + return nil +} + +func TestStartDiscovery_HandlePeerFound(t *testing.T) { + discoveryInterval = 50 * time.Millisecond // Short interval for testing. + + ctx, cancel := context.WithCancel(context.TODO()) + defer cancel() + + gsub := &fakeTopicPeerLister{} + + a := bhost.New(swarmt.GenSwarm(t, ctx)) + err := startDiscovery(ctx, a, gsub) + if err != nil { + t.Errorf("Error when starting discovery: %v", err) + } + + b := bhost.New(swarmt.GenSwarm(t, ctx)) + err = startDiscovery(ctx, b, gsub) + if err != nil { + t.Errorf("Error when starting discovery: %v", err) + } + + // The two hosts should have found each other after 1+ intervals. + time.Sleep(2 * discoveryInterval) + + expectPeers(t, a, 2) + expectPeers(t, b, 2) +} + +func expectPeers(t *testing.T, h *bhost.BasicHost, n int) { + if len(h.Peerstore().Peers()) != n { + t.Errorf( + "Expected %d peer for host %v, but has %d peers. They are: %v.", + n, + h.ID(), + len(h.Peerstore().Peers()), + h.Peerstore().Peers(), + ) + } +} diff --git a/sharding/p2p/feed.go b/sharding/p2p/feed.go index 9e5cd629e..46c3f0b7c 100644 --- a/sharding/p2p/feed.go +++ b/sharding/p2p/feed.go @@ -25,7 +25,16 @@ import ( // msg := <- ch // fmt.Printf("Message received: %v", msg.Data) func (s *Server) Feed(msg interface{}) *event.Feed { - t := reflect.TypeOf(msg) + var t reflect.Type + + // Support passing reflect.Type as the msg. + switch msg.(type) { + case reflect.Type: + t = msg.(reflect.Type) + default: + t = reflect.TypeOf(msg) + } + if s.feeds[t] == nil { s.feeds[t] = new(event.Feed) } diff --git a/sharding/p2p/feed_test.go b/sharding/p2p/feed_test.go index 14ed06c89..96241fc51 100644 --- a/sharding/p2p/feed_test.go +++ b/sharding/p2p/feed_test.go @@ -1,6 +1,9 @@ package p2p -import "testing" +import ( + "reflect" + "testing" +) func TestFeed_ReturnsSameFeed(t *testing.T) { tests := []struct { @@ -13,6 +16,7 @@ func TestFeed_ReturnsSameFeed(t *testing.T) { {a: 'a', b: 'b', want: true}, {a: struct{ c int }{c: 1}, b: struct{ c int }{c: 2}, want: true}, {a: struct{ c string }{c: "a"}, b: struct{ c string }{c: "b"}, want: true}, + {a: reflect.TypeOf(struct{ c int }{c: 1}), b: struct{ c int }{c: 2}, want: true}, // Inequality tests {a: 1, b: '2', want: false}, {a: 'a', b: 1, want: false}, diff --git a/sharding/p2p/message.go b/sharding/p2p/message.go index aea4e1a86..ad78bf855 100644 --- a/sharding/p2p/message.go +++ b/sharding/p2p/message.go @@ -4,6 +4,6 @@ package p2p type Message struct { // Peer represents the sender of the message. Peer Peer - // Data can be any type of message found in sharding/p2p/messages package. + // Data can be any type of message found in sharding/p2p/proto package. Data interface{} } diff --git a/sharding/p2p/messages/messages.go b/sharding/p2p/messages/messages.go deleted file mode 100644 index 65d0c13e6..000000000 --- a/sharding/p2p/messages/messages.go +++ /dev/null @@ -1,31 +0,0 @@ -package messages - -import ( - "math/big" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" -) - -// CollationBodyRequest defines a p2p message being sent over subscription feeds -// by notaries to other notaries or to proposers. -type CollationBodyRequest struct { - ChunkRoot *common.Hash - ShardID *big.Int - Period *big.Int - Proposer *common.Address - Signature [32]byte -} - -// CollationBodyResponse defines the p2p message response sent back -// to the requesting peer. -type CollationBodyResponse struct { - HeaderHash *common.Hash - Body []byte -} - -// TransactionBroadcast defines the p2p message broadcast from simulators -// to the rest of the actors for transactions to be included in collation. -type TransactionBroadcast struct { - Transaction *types.Transaction -} diff --git a/sharding/p2p/options.go b/sharding/p2p/options.go new file mode 100644 index 000000000..8b55bfb54 --- /dev/null +++ b/sharding/p2p/options.go @@ -0,0 +1,29 @@ +package p2p + +import ( + "fmt" + "math/rand" + "time" + + libp2p "github.com/libp2p/go-libp2p" + crypto "github.com/libp2p/go-libp2p-crypto" + ma "github.com/multiformats/go-multiaddr" +) + +var port int32 = 9000 +var portRange int32 = 100 + +// buildOptions for the libp2p host. +// TODO: Expand on these options and provide the option configuration via flags. +// Currently, this is a random port and a (seemingly) consistent private key +// identity. +func buildOptions() []libp2p.Option { + rand.Seed(int64(time.Now().Nanosecond())) + priv, _, _ := crypto.GenerateKeyPair(crypto.Secp256k1, 512) + listen, _ := ma.NewMultiaddr(fmt.Sprintf("/ip4/127.0.0.1/tcp/%d", port+(rand.Int31n(portRange)))) + + return []libp2p.Option{ + libp2p.ListenAddrs(listen), + libp2p.Identity(priv), + } +} diff --git a/sharding/p2p/options_test.go b/sharding/p2p/options_test.go new file mode 100644 index 000000000..cc48cdb73 --- /dev/null +++ b/sharding/p2p/options_test.go @@ -0,0 +1,9 @@ +package p2p + +import "testing" + +func TestBuildOptions(t *testing.T) { + opts := buildOptions() + + _ = opts +} diff --git a/sharding/p2p/service.go b/sharding/p2p/service.go index bba122ba3..6e1349385 100644 --- a/sharding/p2p/service.go +++ b/sharding/p2p/service.go @@ -1,10 +1,25 @@ // Package p2p handles peer-to-peer networking for the sharding package. +// +// Notes: +// Gossip sub topics can be identified by their proto message types. +// +// topic := proto.MessageName(myMsg) +// +// Then we can assume that only these message types are broadcast in that +// gossip subscription. package p2p import ( + "context" "reflect" "github.com/ethereum/go-ethereum/event" + "github.com/golang/protobuf/proto" + + floodsub "github.com/libp2p/go-floodsub" + libp2p "github.com/libp2p/go-libp2p" + host "github.com/libp2p/go-libp2p-host" + pb "github.com/prysmaticlabs/geth-sharding/proto/sharding/v1" log "github.com/sirupsen/logrus" ) @@ -16,24 +31,58 @@ type Sender interface { // Server is a placeholder for a p2p service. To be designed. type Server struct { - feeds map[reflect.Type]*event.Feed + ctx context.Context + cancel context.CancelFunc + feeds map[reflect.Type]*event.Feed + host host.Host + gsub *floodsub.PubSub } // NewServer creates a new p2p server instance. func NewServer() (*Server, error) { + ctx, cancel := context.WithCancel(context.Background()) + opts := buildOptions() + host, err := libp2p.New(ctx, opts...) + if err != nil { + cancel() + return nil, err + } + + gsub, err := floodsub.NewGossipSub(ctx, host) + if err != nil { + cancel() + return nil, err + } + return &Server{ - feeds: make(map[reflect.Type]*event.Feed), + ctx: ctx, + cancel: cancel, + feeds: make(map[reflect.Type]*event.Feed), + host: host, + gsub: gsub, }, nil } // Start the main routine for an p2p server. func (s *Server) Start() { log.Info("Starting shardp2p server") + if err := startDiscovery(s.ctx, s.host, s.gsub); err != nil { + log.Errorf("Could not start p2p discovery! %v", err) + return + } + + // Subscribe to all topics. + for topic, msgType := range topicTypeMapping { + log.Debugf("Subscribing to topic: %s", topic) + go s.subscribeToTopic(topic, msgType) + } } // Stop the main p2p loop. func (s *Server) Stop() error { log.Info("Stopping shardp2p server") + + s.cancel() return nil } @@ -41,10 +90,74 @@ func (s *Server) Stop() error { func (s *Server) Send(msg interface{}, peer Peer) { // TODO // https://github.com/prysmaticlabs/geth-sharding/issues/175 + + // TODO: Support passing value and pointer type messages. + + // TODO: Remove debug log after send is implemented. + _ = peer + log.Debug("Broadcasting to everyone rather than sending a single peer.") + s.Broadcast(msg) } // Broadcast a message to the world. func (s *Server) Broadcast(msg interface{}) { - // TODO - // https://github.com/prysmaticlabs/geth-sharding/issues/176 + // TODO https://github.com/prysmaticlabs/geth-sharding/issues/176 + topic := topic(msg) + log.Debugf("Broadcasting msg on topic %s for message type %T", topic, msg) + + if topic == pb.Topic_UNKNOWN { + log.Warnf("Topic is unknown for message type %T. %v", msg, msg) + } + + // TODO: Next assertion may fail if your msg is not a pointer to a msg. + m, ok := msg.(proto.Message) + if !ok { + log.Errorf("Message to broadcast (type: %T) is not a protobuf message: %v", msg, msg) + return + } + + b, err := proto.Marshal(m) + if err != nil { + log.Errorf("Failed to marshal data for broadcast: %v", err) + return + } + s.gsub.Publish(topic.String(), b) +} + +func (s *Server) subscribeToTopic(topic pb.Topic, msgType reflect.Type) { + sub, err := s.gsub.Subscribe(topic.String()) + if err != nil { + log.Errorf("Failed to subscribe to topic: %v", err) + return + } + defer sub.Cancel() + feed := s.Feed(msgType) + + for { + msg, err := sub.Next(s.ctx) + + if s.ctx.Err() != nil { + return // Context closed or something. + } + if err != nil { + log.Errorf("Failed to get next message: %v", err) + return + } + + // TODO: reflect.Value.Interface() can panic so we should capture that + // panic so the server doesn't crash. + d, ok := reflect.New(msgType).Interface().(proto.Message) + if !ok { + log.Error("Received message is not a protobuf message") + continue + } + err = proto.Unmarshal(msg.Data, d) + if err != nil { + log.Errorf("Failed to decode data: %v", err) + continue + } + + i := feed.Send(Message{Data: d}) + log.Debugf("Send a request to %d subs", i) + } } diff --git a/sharding/p2p/service_test.go b/sharding/p2p/service_test.go index ae13a7808..a7e6cb51e 100644 --- a/sharding/p2p/service_test.go +++ b/sharding/p2p/service_test.go @@ -1,6 +1,133 @@ package p2p -import "github.com/prysmaticlabs/geth-sharding/sharding/types" +import ( + "context" + "io/ioutil" + "reflect" + "testing" + "time" + + "github.com/ethereum/go-ethereum/event" + "github.com/golang/protobuf/proto" + "github.com/prysmaticlabs/geth-sharding/sharding/types" + + floodsub "github.com/libp2p/go-floodsub" + swarmt "github.com/libp2p/go-libp2p-swarm/testing" + bhost "github.com/libp2p/go-libp2p/p2p/host/basic" + pb "github.com/prysmaticlabs/geth-sharding/proto/sharding/v1" + log "github.com/sirupsen/logrus" + logTest "github.com/sirupsen/logrus/hooks/test" +) // Ensure that server implements service. var _ = types.Service(&Server{}) + +func init() { + log.SetLevel(log.DebugLevel) + log.SetOutput(ioutil.Discard) +} + +func TestLifecycle(t *testing.T) { + hook := logTest.NewGlobal() + + s, err := NewServer() + if err != nil { + t.Fatalf("Could not start a new server: %v", err) + } + + s.Start() + msg := hook.Entries[0] + want := "Starting shardp2p server" + if msg == nil || msg.Message != want { + t.Errorf("incorrect log. wanted: %s. got: %v", want, msg) + } + + s.Stop() + msg = hook.LastEntry() + want = "Stopping shardp2p server" + if msg == nil || msg.Message != want { + t.Errorf("incorrect log. wanted: %s. got: %v", want, msg) + } + + // The context should have been cancelled. + if s.ctx.Err() == nil { + t.Error("Context was not cancelled") + } +} + +func TestBroadcast(t *testing.T) { + s, err := NewServer() + if err != nil { + t.Fatalf("Could not start a new server: %v", err) + } + + msg := &pb.CollationBodyRequest{} + s.Broadcast(msg) + + // TODO: test that topic was published +} + +func TestSubscribeToTopic(t *testing.T) { + ctx, cancel := context.WithTimeout(context.TODO(), 1*time.Second) + defer cancel() + h := bhost.New(swarmt.GenSwarm(t, ctx)) + + gsub, err := floodsub.NewFloodSub(ctx, h) + if err != nil { + t.Errorf("Failed to create floodsub: %v", err) + } + + s := Server{ + ctx: ctx, + gsub: gsub, + host: h, + feeds: make(map[reflect.Type]*event.Feed), + } + + feed := s.Feed(pb.CollationBodyRequest{}) + ch := make(chan Message) + sub := feed.Subscribe(ch) + defer sub.Unsubscribe() + + topic := pb.Topic_COLLATION_BODY_REQUEST + msgType := topicTypeMapping[topic] + go s.subscribeToTopic(topic, msgType) + + // Short delay to let goroutine add subscription. + time.Sleep(time.Millisecond * 10) + + // The topic should be subscribed with gsub. + topics := gsub.GetTopics() + if len(topics) < 1 || topics[0] != topic.String() { + t.Errorf("Unexpected subscribed topics: %v. Wanted %s", topics, topic) + } + + pbMsg := &pb.CollationBodyRequest{ShardId: 5} + + done := make(chan bool) + go func() { + // The message should be received from the feed. + msg := <-ch + if !proto.Equal(msg.Data.(proto.Message), pbMsg) { + t.Errorf("Unexpected msg: %+v. Wanted %+v.", msg.Data, pbMsg) + } + + done <- true + }() + + b, err := proto.Marshal(pbMsg) + if err != nil { + t.Errorf("Failed to marshal pbMsg: %v", err) + } + if err = gsub.Publish(topic.String(), b); err != nil { + t.Errorf("Failed to publish message: %v", err) + } + + // Wait for our message assertion to complete. + select { + case <-done: + case <-ctx.Done(): + t.Error("Context timed out before a message was received!") + } + +} diff --git a/sharding/p2p/topics.go b/sharding/p2p/topics.go new file mode 100644 index 000000000..3b9b95101 --- /dev/null +++ b/sharding/p2p/topics.go @@ -0,0 +1,37 @@ +package p2p + +import ( + "reflect" + + pb "github.com/prysmaticlabs/geth-sharding/proto/sharding/v1" +) + +// Mapping of message topic enums to protobuf types. +var topicTypeMapping = map[pb.Topic]reflect.Type{ + pb.Topic_COLLATION_BODY_REQUEST: reflect.TypeOf(pb.CollationBodyRequest{}), + pb.Topic_COLLATION_BODY_RESPONSE: reflect.TypeOf(pb.CollationBodyResponse{}), + pb.Topic_TRANSACTIONS: reflect.TypeOf(pb.Transaction{}), +} + +// Mapping of message types to topic enums. +var typeTopicMapping = reverseMapping(topicTypeMapping) + +// ReverseMapping from K,V to V,K +func reverseMapping(m map[pb.Topic]reflect.Type) map[reflect.Type]pb.Topic { + n := make(map[reflect.Type]pb.Topic) + for k, v := range m { + n[v] = k + } + return n +} + +// Topic returns the given topic for a given interface. This is the preferred +// way to resolve a topic from an value. The msg could be a pointer or value +// argument to resolve to the correct topic. +func topic(msg interface{}) pb.Topic { + msgType := reflect.TypeOf(msg) + if msgType.Kind() == reflect.Ptr { + msgType = reflect.Indirect(reflect.ValueOf(msg)).Type() + } + return typeTopicMapping[msgType] +} diff --git a/sharding/p2p/topics_test.go b/sharding/p2p/topics_test.go new file mode 100644 index 000000000..983d7b259 --- /dev/null +++ b/sharding/p2p/topics_test.go @@ -0,0 +1,62 @@ +package p2p + +import ( + "reflect" + "testing" + + pb "github.com/prysmaticlabs/geth-sharding/proto/sharding/v1" +) + +type testStruct struct{} + +func TestReverseMapping(t *testing.T) { + tests := []struct { + input map[pb.Topic]reflect.Type + want map[reflect.Type]pb.Topic + }{ + { + input: map[pb.Topic]reflect.Type{ + pb.Topic_UNKNOWN: reflect.TypeOf(testStruct{}), + }, + want: map[reflect.Type]pb.Topic{ + reflect.TypeOf(testStruct{}): pb.Topic_UNKNOWN, + }, + }, + } + + for _, tt := range tests { + got := reverseMapping(tt.input) + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("reverseMapping(%+v) = %+v. Wanted %+v", tt.input, got, tt.want) + } + } +} + +func TestTopic(t *testing.T) { + type CustomStruct struct{} + + tests := []struct { + input interface{} + want pb.Topic + }{ + { + input: pb.CollationBodyRequest{}, + want: pb.Topic_COLLATION_BODY_REQUEST, + }, + { + input: &pb.CollationBodyRequest{}, + want: pb.Topic_COLLATION_BODY_REQUEST, + }, + { + input: CustomStruct{}, + want: pb.Topic_UNKNOWN, + }, + } + + for _, tt := range tests { + got := topic(tt.input) + if got != tt.want { + t.Errorf("topic(%T) = %v. wanted %v", tt.input, got, tt.want) + } + } +} diff --git a/sharding/params/BUILD.bazel b/sharding/params/BUILD.bazel index fac9144fd..b71f77b46 100644 --- a/sharding/params/BUILD.bazel +++ b/sharding/params/BUILD.bazel @@ -10,6 +10,7 @@ go_library( go_test( name = "go_default_test", + size = "small", srcs = ["config_test.go"], embed = [":go_default_library"], ) diff --git a/sharding/proposer/BUILD.bazel b/sharding/proposer/BUILD.bazel index 504b1ecbe..78b722aae 100644 --- a/sharding/proposer/BUILD.bazel +++ b/sharding/proposer/BUILD.bazel @@ -9,14 +9,15 @@ go_library( importpath = "github.com/prysmaticlabs/geth-sharding/sharding/proposer", visibility = ["//sharding:__subpackages__"], deps = [ + "//proto/sharding/v1:go_default_library", "//sharding/database:go_default_library", "//sharding/mainchain:go_default_library", "//sharding/p2p:go_default_library", - "//sharding/p2p/messages:go_default_library", "//sharding/params:go_default_library", "//sharding/syncer:go_default_library", "//sharding/txpool:go_default_library", "//sharding/types:go_default_library", + "//shared/legacyutil:go_default_library", "@com_github_ethereum_go_ethereum//accounts:go_default_library", "@com_github_ethereum_go_ethereum//accounts/abi/bind:go_default_library", "@com_github_ethereum_go_ethereum//core/types:go_default_library", @@ -27,6 +28,7 @@ go_library( go_test( name = "go_default_test", + size = "small", srcs = ["service_test.go"], embed = [":go_default_library"], deps = [ diff --git a/sharding/proposer/service.go b/sharding/proposer/service.go index d95fbcc85..3d6c01755 100644 --- a/sharding/proposer/service.go +++ b/sharding/proposer/service.go @@ -8,14 +8,15 @@ import ( gethTypes "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/event" + pb "github.com/prysmaticlabs/geth-sharding/proto/sharding/v1" "github.com/prysmaticlabs/geth-sharding/sharding/database" "github.com/prysmaticlabs/geth-sharding/sharding/mainchain" "github.com/prysmaticlabs/geth-sharding/sharding/p2p" - "github.com/prysmaticlabs/geth-sharding/sharding/p2p/messages" "github.com/prysmaticlabs/geth-sharding/sharding/params" "github.com/prysmaticlabs/geth-sharding/sharding/syncer" "github.com/prysmaticlabs/geth-sharding/sharding/txpool" "github.com/prysmaticlabs/geth-sharding/sharding/types" + "github.com/prysmaticlabs/geth-sharding/shared/legacyutil" log "github.com/sirupsen/logrus" ) @@ -47,14 +48,15 @@ func NewProposer(config *params.Config, client *mainchain.SMCClient, p2p *p2p.Se client, p2p, txpool, - nil, + nil, // txpoolSub dbService, shardID, - nil, + nil, // shard ctx, cancel, sync, - nil}, nil + nil, // msgChan + }, nil } // Start the main loop for proposing collations. @@ -62,7 +64,7 @@ func (p *Proposer) Start() { log.Info("Starting proposer service") p.shard = types.NewShard(big.NewInt(int64(p.shardID)), p.dbService.DB()) p.msgChan = make(chan p2p.Message, 20) - feed := p.p2p.Feed(messages.TransactionBroadcast{}) + feed := p.p2p.Feed(pb.Transaction{}) p.txpoolSub = feed.Subscribe(p.msgChan) go p.proposeCollations() } @@ -78,16 +80,21 @@ func (p *Proposer) Stop() error { // proposeCollations listens to the transaction feed and submits collations over an interval. func (p *Proposer) proposeCollations() { + feed := p.p2p.Feed(pb.Transaction{}) + ch := make(chan p2p.Message, 20) + sub := feed.Subscribe(ch) + defer sub.Unsubscribe() + defer close(ch) for { select { - case msg := <-p.msgChan: - tx, ok := msg.Data.(messages.TransactionBroadcast) + case msg := <-ch: + tx, ok := msg.Data.(*pb.Transaction) if !ok { log.Error("Received incorrect p2p message. Wanted a transaction broadcast message") break } - log.Infof("Received transaction: %x", tx.Transaction.Hash()) - if err := p.createCollation(p.ctx, []*gethTypes.Transaction{tx.Transaction}); err != nil { + // log.Debugf("Received transaction: %x", tx) + if err := p.createCollation(p.ctx, []*gethTypes.Transaction{legacyutil.TransformTransaction(tx)}); err != nil { log.Errorf("Create collation failed: %v", err) } case <-p.ctx.Done(): diff --git a/sharding/simulator/BUILD.bazel b/sharding/simulator/BUILD.bazel index b1eb7c650..57d1efba7 100644 --- a/sharding/simulator/BUILD.bazel +++ b/sharding/simulator/BUILD.bazel @@ -6,13 +6,11 @@ go_library( importpath = "github.com/prysmaticlabs/geth-sharding/sharding/simulator", visibility = ["//sharding:__subpackages__"], deps = [ + "//proto/sharding/v1:go_default_library", "//sharding/mainchain:go_default_library", "//sharding/p2p:go_default_library", - "//sharding/p2p/messages:go_default_library", "//sharding/params:go_default_library", "//sharding/syncer:go_default_library", - "@com_github_ethereum_go_ethereum//common:go_default_library", - "@com_github_ethereum_go_ethereum//core/types:go_default_library", "@com_github_ethereum_go_ethereum//event:go_default_library", "@com_github_sirupsen_logrus//:go_default_library", ], @@ -20,12 +18,12 @@ go_library( go_test( name = "go_default_test", + size = "small", srcs = ["service_test.go"], embed = [":go_default_library"], deps = [ "//sharding/mainchain:go_default_library", "//sharding/p2p:go_default_library", - "//sharding/p2p/messages:go_default_library", "//sharding/params:go_default_library", "//sharding/types:go_default_library", "@com_github_ethereum_go_ethereum//:go_default_library", diff --git a/sharding/simulator/service.go b/sharding/simulator/service.go index d8c4d5de7..d7c6d0fbb 100644 --- a/sharding/simulator/service.go +++ b/sharding/simulator/service.go @@ -4,16 +4,16 @@ import ( "context" "crypto/rand" "math/big" + mrand "math/rand" "time" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/event" "github.com/prysmaticlabs/geth-sharding/sharding/mainchain" "github.com/prysmaticlabs/geth-sharding/sharding/p2p" - "github.com/prysmaticlabs/geth-sharding/sharding/p2p/messages" "github.com/prysmaticlabs/geth-sharding/sharding/params" "github.com/prysmaticlabs/geth-sharding/sharding/syncer" + + pb "github.com/prysmaticlabs/geth-sharding/proto/sharding/v1" log "github.com/sirupsen/logrus" ) @@ -45,8 +45,7 @@ func NewSimulator(config *params.Config, client *mainchain.SMCClient, p2p *p2p.S // Start the main loop for simulating p2p requests. func (s *Simulator) Start() { log.Info("Starting simulator service") - - s.requestFeed = s.p2p.Feed(messages.CollationBodyRequest{}) + s.requestFeed = s.p2p.Feed(pb.CollationBodyRequest{}) go s.broadcastTransactions(time.NewTicker(s.delay).C, s.ctx.Done()) go s.simulateNotaryRequests(s.client.SMCCaller(), s.client.ChainReader(), time.NewTicker(s.delay).C, s.ctx.Done()) @@ -79,18 +78,20 @@ func (s *Simulator) simulateNotaryRequests(fetcher mainchain.RecordFetcher, read } period := new(big.Int).Div(blockNumber.Number(), big.NewInt(s.config.PeriodLength)) + // Collation for current period may not exist yet, so let's ask for + // the collation at period - 1. + period = period.Sub(period, big.NewInt(1)) req, err := syncer.RequestCollationBody(fetcher, big.NewInt(int64(s.shardID)), period) if err != nil { log.Errorf("Error constructing collation body request: %v", err) continue } + if req != nil { - msg := p2p.Message{ - Peer: p2p.Peer{}, - Data: *req, - } - s.requestFeed.Send(msg) - log.Info("Sent request for collation body via a shardp2p feed") + s.p2p.Broadcast(req) + log.Debug("Sent request for collation body via a shardp2p broadcast") + } else { + log.Warn("Syncer generated nil CollationBodyRequest") } } } @@ -107,16 +108,20 @@ func (s *Simulator) broadcastTransactions(delayChan <-chan time.Time, done <-cha return case <-delayChan: tx := createTestTx() - s.p2p.Broadcast(messages.TransactionBroadcast{Transaction: tx}) - log.Debugf("Transaction broadcast with hash: %v", tx.Hash().Hex()) + s.p2p.Broadcast(tx) + log.Debug("Transaction broadcasted") } } } // createTestTx is a helper method to generate tx with random data bytes. // it is used for broadcastTransactions. -func createTestTx() *types.Transaction { +func createTestTx() *pb.Transaction { data := make([]byte, 1024) rand.Read(data) - return types.NewTransaction(0, common.HexToAddress("0x0"), nil, 0, nil, data) + // TODO: add more fields. + return &pb.Transaction{ + Nonce: mrand.Uint64(), + Input: data, + } } diff --git a/sharding/simulator/service_test.go b/sharding/simulator/service_test.go index ca7af8216..e951cd25f 100644 --- a/sharding/simulator/service_test.go +++ b/sharding/simulator/service_test.go @@ -10,14 +10,11 @@ import ( "testing" "time" - "github.com/prysmaticlabs/geth-sharding/sharding/mainchain" - "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" gethTypes "github.com/ethereum/go-ethereum/core/types" - "github.com/prysmaticlabs/geth-sharding/sharding/p2p/messages" - + "github.com/prysmaticlabs/geth-sharding/sharding/mainchain" "github.com/prysmaticlabs/geth-sharding/sharding/p2p" "github.com/prysmaticlabs/geth-sharding/sharding/params" "github.com/prysmaticlabs/geth-sharding/sharding/types" @@ -141,8 +138,6 @@ func TestSimulateNotaryRequests_FaultyReader(t *testing.T) { t.Fatalf("Unable to setup simulator service: %v", err) } - simulator.requestFeed = server.Feed(messages.CollationBodyRequest{}) - delayChan := make(chan time.Time) doneChan := make(chan struct{}) exitRoutine := make(chan bool) @@ -154,7 +149,7 @@ func TestSimulateNotaryRequests_FaultyReader(t *testing.T) { delayChan <- time.Time{} doneChan <- struct{}{} - msg := hook.AllEntries()[0].Message + msg := hook.LastEntry().Message want := "Could not fetch current block number: cannot fetch block by number" if msg != want { t.Errorf("incorrect log, expected %s, got %s", want, msg) @@ -181,8 +176,6 @@ func TestSimulateNotaryRequests_FaultyCaller(t *testing.T) { t.Fatalf("Unable to setup simulator service: %v", err) } - simulator.requestFeed = server.Feed(messages.CollationBodyRequest{}) - delayChan := make(chan time.Time) doneChan := make(chan struct{}) exitRoutine := make(chan bool) @@ -221,7 +214,6 @@ func TestSimulateNotaryRequests(t *testing.T) { t.Fatalf("Unable to setup simulator service: %v", err) } - simulator.requestFeed = server.Feed(messages.CollationBodyRequest{}) delayChan := make(chan time.Time) doneChan := make(chan struct{}) exitRoutine := make(chan bool) @@ -234,8 +226,8 @@ func TestSimulateNotaryRequests(t *testing.T) { delayChan <- time.Time{} doneChan <- struct{}{} - msg := hook.AllEntries()[0].Message - want := "Sent request for collation body via a shardp2p feed" + msg := hook.Entries[1].Message + want := "Sent request for collation body via a shardp2p broadcast" if msg != want { t.Errorf("incorrect log, expected %s, got %s", want, msg) } @@ -255,7 +247,7 @@ func TestBroadcastTransactions(t *testing.T) { t.Fatalf("Unable to setup p2p server: %v", err) } - simulator, err := NewSimulator(params.DefaultConfig, &mainchain.SMCClient{}, server, shardID, 1) + simulator, err := NewSimulator(params.DefaultConfig, &mainchain.SMCClient{}, server, shardID, 1*time.Second) if err != nil { t.Fatalf("Unable to setup simulator service: %v", err) } @@ -272,8 +264,8 @@ func TestBroadcastTransactions(t *testing.T) { delayChan <- time.Time{} doneChan <- struct{}{} - msg := hook.AllEntries()[0].Message - want := "Transaction broadcast with hash" + msg := hook.Entries[1].Message + want := "Transaction broadcasted" if !strings.Contains(msg, want) { t.Errorf("incorrect log, expected %s, got %s", want, msg) } diff --git a/sharding/syncer/BUILD.bazel b/sharding/syncer/BUILD.bazel index 7bfebd546..844723eab 100644 --- a/sharding/syncer/BUILD.bazel +++ b/sharding/syncer/BUILD.bazel @@ -9,10 +9,10 @@ go_library( importpath = "github.com/prysmaticlabs/geth-sharding/sharding/syncer", visibility = ["//sharding:__subpackages__"], deps = [ + "//proto/sharding/v1:go_default_library", "//sharding/database:go_default_library", "//sharding/mainchain:go_default_library", "//sharding/p2p:go_default_library", - "//sharding/p2p/messages:go_default_library", "//sharding/params:go_default_library", "//sharding/types:go_default_library", "@com_github_ethereum_go_ethereum//accounts/abi/bind:go_default_library", @@ -24,17 +24,18 @@ go_library( go_test( name = "go_default_test", + size = "small", srcs = [ "handlers_test.go", "service_test.go", ], embed = [":go_default_library"], deps = [ + "//proto/sharding/v1:go_default_library", "//sharding/contracts:go_default_library", "//sharding/database:go_default_library", "//sharding/mainchain:go_default_library", "//sharding/p2p:go_default_library", - "//sharding/p2p/messages:go_default_library", "//sharding/params:go_default_library", "//sharding/types:go_default_library", "@com_github_ethereum_go_ethereum//accounts:go_default_library", @@ -44,6 +45,7 @@ go_test( "@com_github_ethereum_go_ethereum//core:go_default_library", "@com_github_ethereum_go_ethereum//core/types:go_default_library", "@com_github_ethereum_go_ethereum//crypto:go_default_library", + "@com_github_sirupsen_logrus//:go_default_library", "@com_github_sirupsen_logrus//hooks/test:go_default_library", ], ) diff --git a/sharding/syncer/handlers.go b/sharding/syncer/handlers.go index c0370d645..4c09d3dc9 100644 --- a/sharding/syncer/handlers.go +++ b/sharding/syncer/handlers.go @@ -6,24 +6,34 @@ import ( "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" + pb "github.com/prysmaticlabs/geth-sharding/proto/sharding/v1" "github.com/prysmaticlabs/geth-sharding/sharding/mainchain" "github.com/prysmaticlabs/geth-sharding/sharding/p2p" - "github.com/prysmaticlabs/geth-sharding/sharding/p2p/messages" "github.com/prysmaticlabs/geth-sharding/sharding/types" + log "github.com/sirupsen/logrus" ) // RespondCollationBody is called by a node responding to another node's request // for a collation body given a (shardID, chunkRoot, period, proposerAddress) tuple. // The proposer will fetch the corresponding data from persistent storage (shardDB) by // constructing a collation header from the input and calculating its hash. -func RespondCollationBody(req p2p.Message, collationFetcher types.CollationFetcher) (*messages.CollationBodyResponse, error) { +func RespondCollationBody(req p2p.Message, collationFetcher types.CollationFetcher) (*pb.CollationBodyResponse, error) { // Type assertion helps us catch incorrect data requests. - msg, ok := req.Data.(messages.CollationBodyRequest) + msg, ok := req.Data.(*pb.CollationBodyRequest) if !ok { - return nil, fmt.Errorf("received incorrect data request type: %v", msg) + log.Debugf("Request data type: %T", req.Data) + return nil, fmt.Errorf("received incorrect data request type. Data: %+v", msg) } - header := types.NewCollationHeader(msg.ShardID, msg.ChunkRoot, msg.Period, msg.Proposer, msg.Signature) + shardID := new(big.Int).SetUint64(msg.ShardId) + chunkRoot := common.BytesToHash(msg.ChunkRoot) + period := new(big.Int).SetUint64(msg.Period) + proposer := common.BytesToAddress(msg.ProposerAddress) + var sig [32]byte + if len(msg.Signature) >= 32 { + copy(sig[:], msg.Signature[0:32]) + } + header := types.NewCollationHeader(shardID, &chunkRoot, period, &proposer, sig) // Fetch the collation by its header hash from the shardChainDB. headerHash := header.Hash() @@ -31,15 +41,18 @@ func RespondCollationBody(req p2p.Message, collationFetcher types.CollationFetch if err != nil { return nil, fmt.Errorf("could not fetch collation: %v", err) } + if collation == nil { + return nil, nil + } - return &messages.CollationBodyResponse{HeaderHash: &headerHash, Body: collation.Body()}, nil + return &pb.CollationBodyResponse{HeaderHash: headerHash.Bytes(), Body: collation.Body()}, nil } // RequestCollationBody fetches a collation header record submitted to the SMC for // a shardID, period pair and constructs a p2p collationBodyRequest that will // then be relayed to the appropriate proposer that submitted the collation header. // In production, this will be done within a notary service. -func RequestCollationBody(fetcher mainchain.RecordFetcher, shardID *big.Int, period *big.Int) (*messages.CollationBodyRequest, error) { +func RequestCollationBody(fetcher mainchain.RecordFetcher, shardID *big.Int, period *big.Int) (*pb.CollationBodyRequest, error) { record, err := fetcher.CollationRecords(&bind.CallOpts{}, shardID, period) if err != nil { @@ -52,16 +65,17 @@ func RequestCollationBody(fetcher mainchain.RecordFetcher, shardID *big.Int, per } if sum == 0 { + log.Debugf("No collation exists for shard %d and period %d", shardID, period) return nil, nil } // Converts from fixed size [32]byte to []byte slice. chunkRoot := common.BytesToHash(record.ChunkRoot[:]) - return &messages.CollationBodyRequest{ - ChunkRoot: &chunkRoot, - ShardID: shardID, - Period: period, - Proposer: &record.Proposer, + return &pb.CollationBodyRequest{ + ChunkRoot: chunkRoot.Bytes(), + ShardId: shardID.Uint64(), + Period: period.Uint64(), + ProposerAddress: record.Proposer.Bytes(), }, nil } diff --git a/sharding/syncer/handlers_test.go b/sharding/syncer/handlers_test.go index f158e652a..53b01a019 100644 --- a/sharding/syncer/handlers_test.go +++ b/sharding/syncer/handlers_test.go @@ -15,9 +15,9 @@ import ( "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" + pb "github.com/prysmaticlabs/geth-sharding/proto/sharding/v1" "github.com/prysmaticlabs/geth-sharding/sharding/contracts" "github.com/prysmaticlabs/geth-sharding/sharding/p2p" - "github.com/prysmaticlabs/geth-sharding/sharding/p2p/messages" shardparams "github.com/prysmaticlabs/geth-sharding/sharding/params" shardingTypes "github.com/prysmaticlabs/geth-sharding/sharding/types" ) @@ -147,11 +147,11 @@ func TestCollationBodyResponse(t *testing.T) { proposerAddress := common.BytesToAddress([]byte{}) chunkRoot := common.BytesToHash([]byte{}) - goodReq := messages.CollationBodyRequest{ - ChunkRoot: &chunkRoot, - ShardID: big.NewInt(1), - Period: big.NewInt(1), - Proposer: &proposerAddress, + goodReq := pb.CollationBodyRequest{ + ChunkRoot: chunkRoot.Bytes(), + ShardId: 1, + Period: 1, + ProposerAddress: proposerAddress.Bytes(), } incorrectReq := faultyRequest{} @@ -160,31 +160,41 @@ func TestCollationBodyResponse(t *testing.T) { badMsg := p2p.Message{ Peer: p2p.Peer{}, - Data: incorrectReq, + Data: &incorrectReq, } goodMsg := p2p.Message{ Peer: p2p.Peer{}, - Data: goodReq, + Data: &goodReq, } if _, err := RespondCollationBody(badMsg, fetcher); err == nil { - t.Errorf("Incorrect request should throw error. Expecting messages.CollationBodyRequest{}, received: %v", incorrectReq) + t.Errorf("Incorrect request should throw error. Expecting pb.CollationBodyRequest{}, received: %v", incorrectReq) } if _, err := RespondCollationBody(goodMsg, faultyFetcher); err == nil { t.Error("Faulty collatiom fetcher should cause function to throw error. no error thrown.") } - header := shardingTypes.NewCollationHeader(goodReq.ShardID, goodReq.ChunkRoot, goodReq.Period, goodReq.Proposer, [32]byte{}) + shardID := new(big.Int).SetUint64(goodReq.ShardId) + chunkRoot = common.BytesToHash(goodReq.ChunkRoot) + period := new(big.Int).SetUint64(goodReq.Period) + proposer := common.BytesToAddress(goodReq.ProposerAddress) + + header := shardingTypes.NewCollationHeader( + shardID, + &chunkRoot, + period, + &proposer, + [32]byte{}) body := []byte{} response, err := RespondCollationBody(goodMsg, fetcher) if err != nil { t.Fatalf("Could not construct collation body response: %v", err) } - if response.HeaderHash.Hex() != header.Hash().Hex() { - t.Errorf("Incorrect header hash received. want: %v, received: %v", header.Hash().Hex(), response.HeaderHash.Hex()) + if common.BytesToHash(response.HeaderHash).Hex() != header.Hash().Hex() { + t.Errorf("Incorrect header hash received. want: %v, received: %v", header.Hash().Hex(), common.BytesToHash(response.HeaderHash).Hex()) } if !bytes.Equal(response.Body, body) { @@ -237,19 +247,19 @@ func TestConstructNotaryRequest(t *testing.T) { t.Errorf("constructNotaryRequest should return nil for an inexistent collation header. got: %v", err) } - if request.ChunkRoot.Hex() != chunkRoot.Hex() { - t.Errorf("Chunk root from notary request incorrect. want: %v, got: %v", chunkRoot.Hex(), request.ChunkRoot.Hex()) + if common.BytesToHash(request.ChunkRoot).Hex() != chunkRoot.Hex() { + t.Errorf("Chunk root from notary request incorrect. want: %v, got: %v", chunkRoot.Hex(), common.BytesToHash(request.ChunkRoot).Hex()) } - if request.Proposer.Hex() != proposerAddress.Hex() { - t.Errorf("Proposer address from notary request incorrect. want: %v, got: %v", proposerAddress.Hex(), request.Proposer.Hex()) + if common.BytesToAddress(request.ProposerAddress).Hex() != proposerAddress.Hex() { + t.Errorf("Proposer address from notary request incorrect. want: %v, got: %v", proposerAddress.Hex(), common.BytesToAddress(request.ProposerAddress).Hex()) } - if request.ShardID.Cmp(shardID) != 0 { - t.Errorf("ShardID from notary request incorrect. want: %s, got: %s", shardID, request.ShardID) + if shardID.Uint64() != request.ShardId { + t.Errorf("ShardID from notary request incorrect. want: %d, got: %d", shardID.Uint64(), request.ShardId) } - if request.Period.Cmp(period) != 0 { - t.Errorf("Proposer address from notary request incorrect. want: %s, got: %s", period, request.Period) + if request.Period != period.Uint64() { + t.Errorf("Proposer address from notary request incorrect. want: %d, got: %d", period.Uint64(), request.Period) } } diff --git a/sharding/syncer/service.go b/sharding/syncer/service.go index 6b12d7ee1..861d45741 100644 --- a/sharding/syncer/service.go +++ b/sharding/syncer/service.go @@ -4,11 +4,12 @@ import ( "context" "math/big" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/event" + pb "github.com/prysmaticlabs/geth-sharding/proto/sharding/v1" "github.com/prysmaticlabs/geth-sharding/sharding/database" "github.com/prysmaticlabs/geth-sharding/sharding/mainchain" "github.com/prysmaticlabs/geth-sharding/sharding/p2p" - "github.com/prysmaticlabs/geth-sharding/sharding/p2p/messages" "github.com/prysmaticlabs/geth-sharding/sharding/params" "github.com/prysmaticlabs/geth-sharding/sharding/types" log "github.com/sirupsen/logrus" @@ -45,7 +46,7 @@ func (s *Syncer) Start() { shard := types.NewShard(big.NewInt(int64(s.shardID)), s.shardChainDB.DB()) s.msgChan = make(chan p2p.Message, 100) - s.bodyRequests = s.p2p.Feed(messages.CollationBodyRequest{}).Subscribe(s.msgChan) + s.bodyRequests = s.p2p.Feed(pb.CollationBodyRequest{}).Subscribe(s.msgChan) go s.HandleCollationBodyRequests(shard, s.ctx.Done()) } @@ -71,16 +72,22 @@ func (s *Syncer) HandleCollationBodyRequests(collationFetcher types.CollationFet return case req := <-s.msgChan: if req.Data != nil { - log.Infof("Received p2p request of type: %T", req) + log.Debugf("Received p2p request of type: %T", req.Data) res, err := RespondCollationBody(req, collationFetcher) if err != nil { log.Errorf("Could not construct response: %v", err) continue } + if res == nil { + // TODO: Send that we don't have it? + log.Debug("No response for this collation request. Not sending anything.") + continue + } + // Reply to that specific peer only. - s.p2p.Send(*res, req.Peer) - log.Infof("Responding to p2p request with collation with headerHash: %v", res.HeaderHash.Hex()) + s.p2p.Send(res, req.Peer) + log.Infof("Responding to p2p request with collation with headerHash: 0x%v", common.Bytes2Hex(res.HeaderHash)) } case <-s.bodyRequests.Err(): log.Debugf("Subscriber failed") diff --git a/sharding/syncer/service_test.go b/sharding/syncer/service_test.go index 928962d7b..6f2debca4 100644 --- a/sharding/syncer/service_test.go +++ b/sharding/syncer/service_test.go @@ -2,26 +2,29 @@ package syncer import ( "fmt" + "io/ioutil" "math/big" "testing" - "github.com/prysmaticlabs/geth-sharding/sharding/mainchain" - "github.com/prysmaticlabs/geth-sharding/sharding/params" - "github.com/ethereum/go-ethereum/common" gethTypes "github.com/ethereum/go-ethereum/core/types" - - "github.com/prysmaticlabs/geth-sharding/sharding/p2p/messages" - - logTest "github.com/sirupsen/logrus/hooks/test" - + pb "github.com/prysmaticlabs/geth-sharding/proto/sharding/v1" "github.com/prysmaticlabs/geth-sharding/sharding/database" + "github.com/prysmaticlabs/geth-sharding/sharding/mainchain" "github.com/prysmaticlabs/geth-sharding/sharding/p2p" + "github.com/prysmaticlabs/geth-sharding/sharding/params" "github.com/prysmaticlabs/geth-sharding/sharding/types" + log "github.com/sirupsen/logrus" + logTest "github.com/sirupsen/logrus/hooks/test" ) var _ = types.Service(&Syncer{}) +func init() { + log.SetLevel(log.DebugLevel) + log.SetOutput(ioutil.Discard) +} + func TestStop(t *testing.T) { hook := logTest.NewGlobal() @@ -40,7 +43,7 @@ func TestStop(t *testing.T) { t.Fatalf("Unable to setup sync service: %v", err) } - feed := server.Feed(messages.CollationBodyRequest{}) + feed := server.Feed(pb.CollationBodyRequest{}) syncer.msgChan = make(chan p2p.Message) syncer.bodyRequests = feed.Subscribe(syncer.msgChan) @@ -98,7 +101,7 @@ func TestHandleCollationBodyRequests(t *testing.T) { t.Fatalf("Unable to setup syncer service: %v", err) } - feed := server.Feed(messages.CollationBodyRequest{}) + feed := server.Feed(pb.CollationBodyRequest{}) syncer.msgChan = make(chan p2p.Message) syncer.bodyRequests = feed.Subscribe(syncer.msgChan) @@ -113,24 +116,24 @@ func TestHandleCollationBodyRequests(t *testing.T) { msg := p2p.Message{ Peer: p2p.Peer{}, - Data: messages.CollationBodyRequest{ - ChunkRoot: &chunkRoot, - ShardID: shardID, - Period: period, - Proposer: &proposerAddress, + Data: &pb.CollationBodyRequest{ + ChunkRoot: chunkRoot.Bytes(), + ShardId: shardID.Uint64(), + Period: period.Uint64(), + ProposerAddress: proposerAddress.Bytes(), }, } syncer.msgChan <- msg doneChan <- struct{}{} exitRoutine <- true - logMsg := hook.AllEntries()[0].Message - want := fmt.Sprintf("Received p2p request of type: %T", p2p.Message{}) + logMsg := hook.Entries[0].Message + want := fmt.Sprintf("Received p2p request of type: %T", &pb.CollationBodyRequest{}) if logMsg != want { t.Errorf("incorrect log, expected %s, got %s", want, logMsg) } - logMsg = hook.AllEntries()[1].Message + logMsg = hook.Entries[3].Message want = fmt.Sprintf("Responding to p2p request with collation with headerHash: %v", header.Hash().Hex()) if logMsg != want { t.Errorf("incorrect log, expected %s, got %s", want, logMsg) diff --git a/sharding/types/BUILD.bazel b/sharding/types/BUILD.bazel index cfe90566b..59d231b8c 100644 --- a/sharding/types/BUILD.bazel +++ b/sharding/types/BUILD.bazel @@ -16,6 +16,8 @@ go_library( "@com_github_ethereum_go_ethereum//crypto/sha3:go_default_library", "@com_github_ethereum_go_ethereum//ethdb:go_default_library", "@com_github_ethereum_go_ethereum//rlp:go_default_library", + "@com_github_sirupsen_logrus//:go_default_library", + "@com_github_syndtr_goleveldb//leveldb/errors:go_default_library", ], ) diff --git a/sharding/types/shard.go b/sharding/types/shard.go index a6af7afa8..5f38b74d0 100644 --- a/sharding/types/shard.go +++ b/sharding/types/shard.go @@ -10,6 +10,8 @@ import ( gethTypes "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/rlp" + log "github.com/sirupsen/logrus" + leveldberrors "github.com/syndtr/goleveldb/leveldb/errors" ) // Shard defines a way for services attached to a sharding-enabled node to @@ -45,6 +47,10 @@ func (s *Shard) ValidateShardID(h *CollationHeader) error { // HeaderByHash looks up a collation header from the shardDB using the header's hash. func (s *Shard) HeaderByHash(hash *common.Hash) (*CollationHeader, error) { encoded, err := s.shardDB.Get(hash.Bytes()) + if err != nil && err.Error() == leveldberrors.ErrNotFound.Error() { + log.Debugf("No header found for hash %v", hash.Hex()) + return nil, nil + } if err != nil { return nil, fmt.Errorf("get failed: %v", err) } @@ -69,6 +75,10 @@ func (s *Shard) CollationByHeaderHash(headerHash *common.Hash) (*Collation, erro return nil, fmt.Errorf("cannot fetch header by hash: %v", err) } + if header == nil { + return nil, nil + } + body, err := s.BodyByChunkRoot(header.ChunkRoot()) if err != nil { return nil, fmt.Errorf("cannot fetch body by chunk root: %v", err) diff --git a/shared/debug/debug.go b/shared/debug/debug.go index d0656dc36..a06bb55c7 100644 --- a/shared/debug/debug.go +++ b/shared/debug/debug.go @@ -314,6 +314,9 @@ func MigrateFlags(action func(ctx *cli.Context) error) func(*cli.Context) error // Setup initializes profiling based on the CLI flags. // It should be called as early as possible in the program. func Setup(ctx *cli.Context) error { + // TODO: Set verbosity level from flag. + log.SetLevel(log.DebugLevel) + // profiling, tracing runtime.MemProfileRate = ctx.GlobalInt(MemProfileRateFlag.Name) if traceFile := ctx.GlobalString(TraceFlag.Name); traceFile != "" { diff --git a/sharding/p2p/messages/BUILD.bazel b/shared/legacyutil/BUILD.bazel similarity index 56% rename from sharding/p2p/messages/BUILD.bazel rename to shared/legacyutil/BUILD.bazel index 7e18dbdfb..49ba49b22 100644 --- a/sharding/p2p/messages/BUILD.bazel +++ b/shared/legacyutil/BUILD.bazel @@ -2,10 +2,11 @@ load("@io_bazel_rules_go//go:def.bzl", "go_library") go_library( name = "go_default_library", - srcs = ["messages.go"], - importpath = "github.com/prysmaticlabs/geth-sharding/sharding/p2p/messages", - visibility = ["//sharding:__subpackages__"], + srcs = ["convert_transaction.go"], + importpath = "github.com/prysmaticlabs/geth-sharding/shared/legacyutil", + visibility = ["//visibility:public"], deps = [ + "//proto/sharding/v1:go_default_library", "@com_github_ethereum_go_ethereum//common:go_default_library", "@com_github_ethereum_go_ethereum//core/types:go_default_library", ], diff --git a/shared/legacyutil/convert_transaction.go b/shared/legacyutil/convert_transaction.go new file mode 100644 index 000000000..86584ed06 --- /dev/null +++ b/shared/legacyutil/convert_transaction.go @@ -0,0 +1,23 @@ +// This package exists to convert Ethererum 2.0 types to go-ethereum or +// Ethereum 1.0 types. +package legacyutil + +import ( + "math/big" + + "github.com/ethereum/go-ethereum/common" + gethTypes "github.com/ethereum/go-ethereum/core/types" + pb "github.com/prysmaticlabs/geth-sharding/proto/sharding/v1" +) + +// TransformTransaction of proto transaction to geth's transction. +func TransformTransaction(t *pb.Transaction) *gethTypes.Transaction { + return gethTypes.NewTransaction( + t.Nonce, + common.BytesToAddress(t.Recipient), + big.NewInt(0).SetUint64(t.Value), + t.GasLimit, + big.NewInt(0).SetUint64(t.GasPrice), + t.Input, + ) +}