diff --git a/lotus-soup/_compositions/sync-mining.toml b/lotus-soup/_compositions/sync-mining.toml new file mode 100644 index 00000000..115b38aa --- /dev/null +++ b/lotus-soup/_compositions/sync-mining.toml @@ -0,0 +1,41 @@ +[metadata] + name = "lotus-soup" + author = "raulk" + +[global] + plan = "lotus-soup" + case = "sync-mining" + total_instances = 4 + builder = "exec:go" + runner = "local:exec" + + build = { selectors = ["testground"] } + build_config = { enable_go_build_cache = true } + run_config = { exposed_ports = ["6060", "1234", "2345"] } + +[global.run.test_params] + clients = "1" + miners = "2" + genesis_timestamp_offset = "0" + balance = "2000000000" + sectors = "10" + random_beacon_type = "mock" + mining_mode = "synchronized" + +[[groups]] + id = "bootstrapper" + instances = { count = 1 } + [groups.run.test_params] + role = "bootstrapper" + +[[groups]] + id = "miners" + instances = { count = 2 } + [groups.run.test_params] + role = "miner" + +[[groups]] + id = "clients" + instances = { count = 1 } + [groups.run.test_params] + role = "client" diff --git a/lotus-soup/go.mod b/lotus-soup/go.mod index 4f3997a0..2bb9c0f8 100644 --- a/lotus-soup/go.mod +++ b/lotus-soup/go.mod @@ -5,14 +5,15 @@ go 1.14 require ( contrib.go.opencensus.io/exporter/prometheus v0.1.0 github.com/davecgh/go-spew v1.1.1 - github.com/drand/drand v0.9.2-0.20200616080806-a94e9c1636a4 + github.com/drand/drand v1.0.3-0.20200714175734-29705eaf09d4 github.com/filecoin-project/go-address v0.0.2-0.20200504173055-8b6f2fb2b3ef - github.com/filecoin-project/go-fil-markets v0.4.0 + github.com/filecoin-project/go-fil-markets v0.4.1-0.20200715201050-c141144ea312 github.com/filecoin-project/go-jsonrpc v0.1.1-0.20200602181149-522144ab4e24 github.com/filecoin-project/go-storedcounter v0.0.0-20200421200003-1c99c62e8a5b - github.com/filecoin-project/lotus v0.4.2-0.20200708212122-7d841dbfa81c - github.com/filecoin-project/specs-actors v0.7.1 + github.com/filecoin-project/lotus v0.4.2-0.20200716093446-6092854ecee2 + github.com/filecoin-project/specs-actors v0.7.2 github.com/gorilla/mux v1.7.4 + github.com/hashicorp/go-multierror v1.1.0 github.com/influxdata/influxdb v1.8.0 // indirect github.com/ipfs/go-cid v0.0.6 github.com/ipfs/go-datastore v0.4.4 @@ -23,13 +24,18 @@ require ( github.com/ipfs/go-unixfs v0.2.4 github.com/ipld/go-car v0.1.1-0.20200526133713-1c7508d55aae github.com/kpacha/opencensus-influxdb v0.0.0-20181102202715-663e2683a27c + github.com/lib/pq v1.7.0 // indirect github.com/libp2p/go-libp2p v0.10.0 github.com/libp2p/go-libp2p-core v0.6.0 github.com/libp2p/go-libp2p-pubsub-tracer v0.0.0-20200626141350-e730b32bf1e6 github.com/multiformats/go-multiaddr v0.2.2 github.com/multiformats/go-multiaddr-net v0.1.5 - github.com/testground/sdk-go v0.2.3-0.20200706132230-6a65ddac2d8c + github.com/prometheus/common v0.10.0 + github.com/raulk/clock v1.1.0 + github.com/testground/sdk-go v0.2.3-0.20200716112730-420be929ef43 + github.com/xorcare/golden v0.6.1-0.20191112154924-b87f686d7542 // indirect go.opencensus.io v0.22.4 + go.uber.org/fx v1.9.0 ) // This will work in all build modes: docker:go, exec:go, and local go build. diff --git a/lotus-soup/go.sum b/lotus-soup/go.sum index 68134c4c..f7cbc405 100644 --- a/lotus-soup/go.sum +++ b/lotus-soup/go.sum @@ -88,6 +88,7 @@ github.com/avast/retry-go v2.6.0+incompatible h1:FelcMrm7Bxacr1/RM8+/eqkDkmVN7tj github.com/avast/retry-go v2.6.0+incompatible/go.mod h1:XtSnn+n/sHqQIpZ10K1qAevBhOOCWBLXXy3hyiqqBrY= github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU= github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= +github.com/aws/aws-sdk-go v1.32.11/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0= github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g= github.com/beevik/ntp v0.2.0/go.mod h1:hIHWr+l3+/clUnF44zdK+CWW7fO8dR5cIylAQ76NRpg= github.com/benbjohnson/clock v1.0.1/go.mod h1:bGMdMPoPVvcYyt1gHDf4J2KE153Yf9BuiUKYMaxlTDM= @@ -101,6 +102,7 @@ github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kB github.com/bmizerany/pat v0.0.0-20170815010413-6226ea591a40/go.mod h1:8rLXio+WjiTceGBHIoTvn60HIbs7Hm7bcHjyrSqYB9c= github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps= github.com/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625/go.mod h1:HYsPBTaaSFSlLx/70C2HPIMNZpVV8+vt/A+FMnYP11g= +github.com/briandowns/spinner v1.11.1/go.mod h1:QOuQk7x+EaDASo80FEXwlwiA+j/PPIcX3FScO+3/ZPQ= github.com/btcsuite/btcd v0.0.0-20190213025234-306aecffea32/go.mod h1:DrZx5ec/dmnfpw9KyYoQyYo7d0KEvTkk/5M/vbZjAr8= github.com/btcsuite/btcd v0.0.0-20190523000118-16327141da8c/go.mod h1:3J08xEfcugPacsc34/LKRU2yO7YmuT8yt28J8k2+rrI= github.com/btcsuite/btcd v0.0.0-20190605094302-a0d1e3e36d50/go.mod h1:3J08xEfcugPacsc34/LKRU2yO7YmuT8yt28J8k2+rrI= @@ -190,10 +192,14 @@ github.com/drand/bls12-381 v0.3.2 h1:RImU8Wckmx8XQx1tp1q04OV73J9Tj6mmpQLYDP7V1XE github.com/drand/bls12-381 v0.3.2/go.mod h1:dtcLgPtYT38L3NO6mPDYH0nbpc5tjPassDqiniuAt4Y= github.com/drand/drand v0.9.2-0.20200616080806-a94e9c1636a4 h1:wEpu4hGFF0m0uDq/gxT9Ca/HWek0tvsMqsyPpLBWJ/E= github.com/drand/drand v0.9.2-0.20200616080806-a94e9c1636a4/go.mod h1:Bu8QYdU0YdB2ZQZezHxabmOIciddiwLRnyV4nuZ2HQE= +github.com/drand/drand v1.0.3-0.20200714175734-29705eaf09d4 h1:+Rov3bfUriGWFR/lUVXnpimx+HMr9BXRC4by0BxuQ8k= +github.com/drand/drand v1.0.3-0.20200714175734-29705eaf09d4/go.mod h1:SnqWL9jksIMK63UKkfmWI6f9PDN8ROoCgg+Z4zWk7hg= github.com/drand/kyber v1.0.1-0.20200110225416-8de27ed8c0e2/go.mod h1:UpXoA0Upd1N9l4TvRPHr1qAUBBERj6JQ/mnKI3BPEmw= github.com/drand/kyber v1.0.2/go.mod h1:x6KOpK7avKj0GJ4emhXFP5n7M7W7ChAPmnQh/OL6vRw= github.com/drand/kyber v1.1.0 h1:uBfD8gwpVufr+7Dvbxi4jGQ+qoMCO5tRfhYPyn+Tpqk= github.com/drand/kyber v1.1.0/go.mod h1:x6KOpK7avKj0GJ4emhXFP5n7M7W7ChAPmnQh/OL6vRw= +github.com/drand/kyber v1.1.1 h1:mwCY2XGRB+Qc1MPfrnRuVuXELkPhcq/r9yMoJIcDhHI= +github.com/drand/kyber v1.1.1/go.mod h1:x6KOpK7avKj0GJ4emhXFP5n7M7W7ChAPmnQh/OL6vRw= github.com/drand/kyber-bls12381 v0.1.0 h1:/P4C65VnyEwxzR5ZYYVMNzY1If+aYBrdUU5ukwh7LQw= github.com/drand/kyber-bls12381 v0.1.0/go.mod h1:N1emiHpm+jj7kMlxEbu3MUyOiooTgNySln564cgD9mk= github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= @@ -220,8 +226,10 @@ github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5Kwzbycv github.com/fatih/color v1.8.0 h1:5bzFgL+oy7JITMTxUPJ00n7VxmYd/PdMp5mHFX40/RY= github.com/fatih/color v1.8.0/go.mod h1:3l45GVGkyrnYNl9HoIjnp2NnNWvh6hLAqD8yTfGjnw8= github.com/fd/go-nat v1.0.0/go.mod h1:BTBu/CKvMmOMUPkKVef1pngt2WFH/lg7E6yQnulfp6E= +github.com/filecoin-project/chain-validation v0.0.6-0.20200615191232-6be1a8c6ed09/go.mod h1:HEJn6kOXMNhCNBYNTO/lrEI7wSgqCOR6hN5ecfYUnC8= github.com/filecoin-project/chain-validation v0.0.6-0.20200701165912-3b6aaaa32a66 h1:LyYxtZe2SA2U0MV+hmDFtUHkLyvYauaahPpPZsF8Fdw= github.com/filecoin-project/chain-validation v0.0.6-0.20200701165912-3b6aaaa32a66/go.mod h1:Tr0C0rl7WCPkkQOkrOLDR6k1ppFVgoIuj1s4KPs4bzo= +github.com/filecoin-project/chain-validation v0.0.6-0.20200713115604-652494bba69e/go.mod h1:293UFGwKduXCuIC2/5pIepH7lof+L9fNiPku/+arST4= github.com/filecoin-project/go-address v0.0.0-20200107215422-da8eea2842b5/go.mod h1:SAOwJoakQ8EPjwNIsiakIQKsoKdkcbx8U3IapgCg9R0= github.com/filecoin-project/go-address v0.0.2-0.20200218010043-eb9bb40ed5be/go.mod h1:SAOwJoakQ8EPjwNIsiakIQKsoKdkcbx8U3IapgCg9R0= github.com/filecoin-project/go-address v0.0.2-0.20200504173055-8b6f2fb2b3ef h1:Wi5E+P1QfHP8IF27eUiTx5vYfqQZwfPxzq3oFEq8w8U= @@ -232,18 +240,30 @@ github.com/filecoin-project/go-amt-ipld/v2 v2.0.1-0.20200424220931-6263827e49f2/ github.com/filecoin-project/go-bitfield v0.0.0-20200416002808-b3ee67ec9060/go.mod h1:iodsLxOFZnqKtjj2zkgqzoGNrv6vUqj69AT/J8DKXEw= github.com/filecoin-project/go-bitfield v0.0.1/go.mod h1:Ry9/iUlWSyjPUzlAvdnfy4Gtvrq4kWmWDztCU1yEgJY= github.com/filecoin-project/go-bitfield v0.0.2-0.20200518150651-562fdb554b6e/go.mod h1:Ry9/iUlWSyjPUzlAvdnfy4Gtvrq4kWmWDztCU1yEgJY= +github.com/filecoin-project/go-bitfield v0.0.2-0.20200629135455-587b27927d38 h1:B2gUde2DlfCb5YMYNVems2orobxC3KhrX3migym1IOQ= +github.com/filecoin-project/go-bitfield v0.0.2-0.20200629135455-587b27927d38/go.mod h1:Ry9/iUlWSyjPUzlAvdnfy4Gtvrq4kWmWDztCU1yEgJY= +github.com/filecoin-project/go-bitfield v0.0.3/go.mod h1:Ry9/iUlWSyjPUzlAvdnfy4Gtvrq4kWmWDztCU1yEgJY= github.com/filecoin-project/go-bitfield v0.0.4-0.20200703174658-f4a5758051a1 h1:xuHlrdznafh7ul5t4xEncnA4qgpQvJZEw+mr98eqHXw= github.com/filecoin-project/go-bitfield v0.0.4-0.20200703174658-f4a5758051a1/go.mod h1:Ry9/iUlWSyjPUzlAvdnfy4Gtvrq4kWmWDztCU1yEgJY= github.com/filecoin-project/go-cbor-util v0.0.0-20191219014500-08c40a1e63a2 h1:av5fw6wmm58FYMgJeoB/lK9XXrgdugYiTqkdxjTy9k8= github.com/filecoin-project/go-cbor-util v0.0.0-20191219014500-08c40a1e63a2/go.mod h1:pqTiPHobNkOVM5thSRsHYjyQfq7O5QSCMhvuu9JoDlg= github.com/filecoin-project/go-crypto v0.0.0-20191218222705-effae4ea9f03 h1:2pMXdBnCiXjfCYx/hLqFxccPoqsSveQFxVLvNxy9bus= github.com/filecoin-project/go-crypto v0.0.0-20191218222705-effae4ea9f03/go.mod h1:+viYnvGtUTgJRdy6oaeF4MTFKAfatX071MPDPBL11EQ= +github.com/filecoin-project/go-data-transfer v0.3.0 h1:BwBrrXu9Unh9JjjX4GAc5FfzUNioor/aATIjfc7JTBg= +github.com/filecoin-project/go-data-transfer v0.3.0/go.mod h1:cONglGP4s/d+IUQw5mWZrQK+FQATQxr3AXzi4dRh0l4= github.com/filecoin-project/go-data-transfer v0.4.0 h1:xiC0qVZten8VtqEs5rRjyz2n/nZ8prbZSWvAr1V+CBE= github.com/filecoin-project/go-data-transfer v0.4.0/go.mod h1:5ksROBkSREsb2O4h5vBcGMr9lXTpfeyjHo8o0yxf6FQ= +github.com/filecoin-project/go-data-transfer v0.4.1-0.20200715144713-b3311844e1a5 h1:/OZ+nr0x3uMZCPrreuUbS5EUOFm9DDo4ljgdav8rp/s= +github.com/filecoin-project/go-data-transfer v0.4.1-0.20200715144713-b3311844e1a5/go.mod h1:duGDSKvsOxiKl6Dueh8DNA6ZbiM30PWUWlSKjo9ac+o= +github.com/filecoin-project/go-data-transfer v0.5.0 h1:pvWlab69BD5dwheRHjjBjFB6m7CEqEZeI+aChtVqKVk= github.com/filecoin-project/go-fil-commcid v0.0.0-20200208005934-2b8bd03caca5 h1:yvQJCW9mmi9zy+51xA01Ea2X7/dL7r8eKDPuGUjRmbo= github.com/filecoin-project/go-fil-commcid v0.0.0-20200208005934-2b8bd03caca5/go.mod h1:JbkIgFF/Z9BDlvrJO1FuKkaWsH673/UdFaiVS6uIHlA= +github.com/filecoin-project/go-fil-markets v0.3.2-0.20200702145639-4034a18364e4 h1:VqNmKGy4/ryzo/TqevSa1kancc3hSdws7sl/NCTZzT0= +github.com/filecoin-project/go-fil-markets v0.3.2-0.20200702145639-4034a18364e4/go.mod h1:UY+/zwNXHN73HcrN6HxNDpv6KKM6ehqfCuE9vK9khF8= github.com/filecoin-project/go-fil-markets v0.4.0 h1:toDPViYyQOHtUs6jl0KB9EzgdfCxXR11dZO/rqWbFtU= github.com/filecoin-project/go-fil-markets v0.4.0/go.mod h1:VAH6h+sWuhPAsSwAS9Kecx8MI/dIjFkrLO8jJUmLWQc= +github.com/filecoin-project/go-fil-markets v0.4.1-0.20200715201050-c141144ea312 h1:oVZggNjDWZWEjomkxPl8U3jrOLURoS4QSZA6t4YU5BY= +github.com/filecoin-project/go-fil-markets v0.4.1-0.20200715201050-c141144ea312/go.mod h1:MvrpKOiETu39e9H167gdQzdzLNcvHsUp48UkXqPSdtU= github.com/filecoin-project/go-jsonrpc v0.1.1-0.20200602181149-522144ab4e24 h1:Jc7vkplmZYVuaEcSXGHDwefvZIdoyyaoGDLqSr8Svms= github.com/filecoin-project/go-jsonrpc v0.1.1-0.20200602181149-522144ab4e24/go.mod h1:j6zV//WXIIY5kky873Q3iIKt/ViOE8rcijovmpxrXzM= github.com/filecoin-project/go-padreader v0.0.0-20200210211231-548257017ca6 h1:92PET+sx1Hb4W/8CgFwGuxaKbttwY+UNspYZTvXY0vs= @@ -253,31 +273,53 @@ github.com/filecoin-project/go-paramfetch v0.0.2-0.20200218225740-47c639bab663/g github.com/filecoin-project/go-paramfetch v0.0.2-0.20200701152213-3e0f0afdc261 h1:A256QonvzRaknIIAuWhe/M2dpV2otzs3NBhi5TWa/UA= github.com/filecoin-project/go-paramfetch v0.0.2-0.20200701152213-3e0f0afdc261/go.mod h1:fZzmf4tftbwf9S37XRifoJlz7nCjRdIrMGLR07dKLCc= github.com/filecoin-project/go-statemachine v0.0.0-20200226041606-2074af6d51d9/go.mod h1:FGwQgZAt2Gh5mjlwJUlVB62JeYdo+if0xWxSEfBD9ig= +github.com/filecoin-project/go-statemachine v0.0.0-20200612181802-4eb3d0c68eba h1:GEWb/6KQyNZt4jm8fgVcIFPH0ElAGXfHM59ZSiqPTvY= +github.com/filecoin-project/go-statemachine v0.0.0-20200612181802-4eb3d0c68eba/go.mod h1:FGwQgZAt2Gh5mjlwJUlVB62JeYdo+if0xWxSEfBD9ig= github.com/filecoin-project/go-statemachine v0.0.0-20200703171610-a74a697973b9 h1:NagIOq5osclBprc95ILEnGCOpubuhalqwWvayYJmXLQ= github.com/filecoin-project/go-statemachine v0.0.0-20200703171610-a74a697973b9/go.mod h1:FGwQgZAt2Gh5mjlwJUlVB62JeYdo+if0xWxSEfBD9ig= +github.com/filecoin-project/go-statemachine v0.0.0-20200714194326-a77c3ae20989 h1:1GjCS3xy/CRIw7Tq0HfzX6Al8mklrszQZ3iIFnjPzHk= +github.com/filecoin-project/go-statemachine v0.0.0-20200714194326-a77c3ae20989/go.mod h1:FGwQgZAt2Gh5mjlwJUlVB62JeYdo+if0xWxSEfBD9ig= github.com/filecoin-project/go-statestore v0.1.0 h1:t56reH59843TwXHkMcwyuayStBIiWBRilQjQ+5IiwdQ= github.com/filecoin-project/go-statestore v0.1.0/go.mod h1:LFc9hD+fRxPqiHiaqUEZOinUJB4WARkRfNl10O7kTnI= github.com/filecoin-project/go-storedcounter v0.0.0-20200421200003-1c99c62e8a5b h1:fkRZSPrYpk42PV3/lIXiL0LHetxde7vyYYvSsttQtfg= github.com/filecoin-project/go-storedcounter v0.0.0-20200421200003-1c99c62e8a5b/go.mod h1:Q0GQOBtKf1oE10eSXSlhN45kDBdGvEcVOqMiffqX+N8= -github.com/filecoin-project/lotus v0.4.2-0.20200708212122-7d841dbfa81c h1:eqLJHtS/fTYeYX90iUYU79x5FNlVihvYr2TNGRuDFYk= -github.com/filecoin-project/lotus v0.4.2-0.20200708212122-7d841dbfa81c/go.mod h1:q1K9ZdcmxhZJhzFpFtg/peJVoMMXIUE1rRDurQToI7Q= +github.com/filecoin-project/lotus v0.4.2-0.20200713102953-973dbd6a1371 h1:tRcxTxZ9Vf6/zZ4sH/1f8kC584up8fWhPwqJXS9xuEA= +github.com/filecoin-project/lotus v0.4.2-0.20200713102953-973dbd6a1371/go.mod h1:Q6rc5AyzGOKcHsjNGN5c4v4tsV4UPXB/zu199QYuAZo= +github.com/filecoin-project/lotus v0.4.2-0.20200716093446-6092854ecee2 h1:C8FXDivwIk1EFwJqCdhPP7fqXDxGuH2wR9qAoIT8JzQ= +github.com/filecoin-project/lotus v0.4.2-0.20200716093446-6092854ecee2/go.mod h1:l3xfz32ZiSl11kwFgCgLP0L1FsnkaYV+j+CjYXO+hQU= +github.com/filecoin-project/lotus v0.4.2-0.20200716094953-a87899ddb6b3 h1:46B5ZEv/rEZ5p1lxFxiJRMsf1VC3UT2QL7gZ19hrE2c= +github.com/filecoin-project/lotus v0.4.2-0.20200716094953-a87899ddb6b3/go.mod h1:gS463iRKNd+Is8p1R+lQ4tuE+mdudY//L3Eg1Hs9Jrc= github.com/filecoin-project/sector-storage v0.0.0-20200615154852-728a47ab99d6/go.mod h1:M59QnAeA/oV+Z8oHFLoNpGMv0LZ8Rll+vHVXX7GirPM= github.com/filecoin-project/sector-storage v0.0.0-20200625154333-98ef8e4ef246/go.mod h1:8f0hWDzzIi1hKs4IVKH9RnDsO4LEHVz8BNat0okDOuY= -github.com/filecoin-project/sector-storage v0.0.0-20200708195134-e3b9ba01c287 h1:lMzTlms23AnWKx7+Bq0nMqSCnuE1tcMkMwtT8zfS7gE= -github.com/filecoin-project/sector-storage v0.0.0-20200708195134-e3b9ba01c287/go.mod h1:salgVdX7qeXFo/xaiEQE29J4pPkjn71T0kt0n+VDBzo= +github.com/filecoin-project/sector-storage v0.0.0-20200630180318-4c1968f62a8f h1:EHKqNJNIcYggqfrd5nu7SV1KR93ReZygfdSV0w/jefQ= +github.com/filecoin-project/sector-storage v0.0.0-20200630180318-4c1968f62a8f/go.mod h1:r12d7tsmJKz8QDGoCvl65Ay2al6mOgDqxAGUxbyrgMs= +github.com/filecoin-project/sector-storage v0.0.0-20200709184611-f0dae546b517 h1:bnYiOUDKxJtFk6jtGWSiXSYq3TeSKGx6BOjb2wa1SwQ= +github.com/filecoin-project/sector-storage v0.0.0-20200709184611-f0dae546b517/go.mod h1:salgVdX7qeXFo/xaiEQE29J4pPkjn71T0kt0n+VDBzo= +github.com/filecoin-project/sector-storage v0.0.0-20200712023225-1d67dcfa3c15 h1:miw6hiusb/MkV1ryoqUKKWnvHhPW00AYtyeCj0L8pqo= +github.com/filecoin-project/sector-storage v0.0.0-20200712023225-1d67dcfa3c15/go.mod h1:salgVdX7qeXFo/xaiEQE29J4pPkjn71T0kt0n+VDBzo= github.com/filecoin-project/specs-actors v0.0.0-20200210130641-2d1fbd8672cf/go.mod h1:xtDZUB6pe4Pksa/bAJbJ693OilaC5Wbot9jMhLm3cZA= github.com/filecoin-project/specs-actors v0.3.0/go.mod h1:nQYnFbQ7Y0bHZyq6HDEuVlCPR+U3z5Q3wMOQ+2aiV+Y= github.com/filecoin-project/specs-actors v0.6.0/go.mod h1:dRdy3cURykh2R8O/DKqy8olScl70rmIS7GrB4hB1IDY= github.com/filecoin-project/specs-actors v0.6.1/go.mod h1:dRdy3cURykh2R8O/DKqy8olScl70rmIS7GrB4hB1IDY= +github.com/filecoin-project/specs-actors v0.6.2-0.20200702170846-2cd72643a5cf h1:2ERozAZteHYef3tVLVJRepzYieLtJdxvfXNUel19CeU= +github.com/filecoin-project/specs-actors v0.6.2-0.20200702170846-2cd72643a5cf/go.mod h1:dRdy3cURykh2R8O/DKqy8olScl70rmIS7GrB4hB1IDY= github.com/filecoin-project/specs-actors v0.7.0/go.mod h1:+z0htZu/wLBDbOLcQTKKUEC2rkUTFzL2KJ/bRAVWkws= github.com/filecoin-project/specs-actors v0.7.1 h1:/zW++MN4gGIPvG+s0zmSI97k0Z/aaeiREjLC10gQbco= github.com/filecoin-project/specs-actors v0.7.1/go.mod h1:+z0htZu/wLBDbOLcQTKKUEC2rkUTFzL2KJ/bRAVWkws= +github.com/filecoin-project/specs-actors v0.7.2 h1:zMOU6LJS3gz7E9rwPPiPgTVawe7ypUWK9ugPBiaDZGc= +github.com/filecoin-project/specs-actors v0.7.2/go.mod h1:oJMdZvXSDZWWvjDxCkAywNz2MhgxV6dBzSCVg4vNf4o= github.com/filecoin-project/specs-storage v0.1.0/go.mod h1:Pr5ntAaxsh+sLG/LYiL4tKzvA83Vk5vLODYhfNwOg7k= github.com/filecoin-project/specs-storage v0.1.1-0.20200622113353-88a9704877ea h1:iixjULRQFPn7Q9KlIqfwLJnlAXO10bbkI+xy5GKGdLY= github.com/filecoin-project/specs-storage v0.1.1-0.20200622113353-88a9704877ea/go.mod h1:Pr5ntAaxsh+sLG/LYiL4tKzvA83Vk5vLODYhfNwOg7k= +github.com/filecoin-project/storage-fsm v0.0.0-20200625160832-379a4655b044 h1:i4oMhv1kx/MAUxRN4EM5tag5fI1uagrwQwINgKrzUt4= +github.com/filecoin-project/storage-fsm v0.0.0-20200625160832-379a4655b044/go.mod h1:JD7fmV1BYADDcy4EYQnqFH/rUzXsh0Je0jXarCjZqSk= github.com/filecoin-project/storage-fsm v0.0.0-20200707194229-bc5e298e2b4c h1:F6guH363a+fpew1zkgoez4/U0RqW4ph6GVXR23lVwng= github.com/filecoin-project/storage-fsm v0.0.0-20200707194229-bc5e298e2b4c/go.mod h1:SXO4VnXG056B/lXHL8HZv54eMqlsyynm+v93BlLwlOY= +github.com/filecoin-project/storage-fsm v0.0.0-20200715191202-7e92e888bf41 h1:K2DI5+IKuY0cOjX/r1Agy6rYcAhU89LVNOjutCUib4g= +github.com/filecoin-project/storage-fsm v0.0.0-20200715191202-7e92e888bf41/go.mod h1:TDNjb0HYG2fppxWH5EsiNCZu97iJZNuPYmivSK13Ao0= github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= +github.com/flynn/noise v0.0.0-20180327030543-2492fe189ae6 h1:u/UEqS66A5ckRmS4yNpjmVH56sVtS/RfclBAYocb4as= +github.com/flynn/noise v0.0.0-20180327030543-2492fe189ae6/go.mod h1:1i71OnUq3iUe1ma7Lr6yG6/rjvM3emb6yoL7xLFzcVQ= github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= github.com/francoispqt/gojay v1.2.13 h1:d2m3sFjloqoIUQU3TsHBgj6qg/BVGlTBeHDUmyJnXKk= github.com/francoispqt/gojay v1.2.13/go.mod h1:ehT5mTG4ua4581f1++1WLG0vPdaA9HaiDsoyrBGkyDY= @@ -310,6 +352,7 @@ github.com/go-redis/redis/v7 v7.4.0 h1:7obg6wUoj05T0EpY0o8B59S9w5yeMWql7sw2kwNW1 github.com/go-redis/redis/v7 v7.4.0/go.mod h1:JDNMw23GTyLNC4GZu9njt15ctBQVn7xjRfnwdHj/Dcg= github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= +github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/godbus/dbus v0.0.0-20190402143921-271e53dc4968/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw= @@ -534,8 +577,12 @@ github.com/ipfs/go-filestore v1.0.0 h1:QR7ekKH+q2AGiWDc7W2Q0qHuYSRZGUJqUn0GsegEP github.com/ipfs/go-filestore v1.0.0/go.mod h1:/XOCuNtIe2f1YPbiXdYvD0BKLA0JR1MgPiFOdcuu9SM= github.com/ipfs/go-fs-lock v0.0.1 h1:XHX8uW4jQBYWHj59XXcjg7BHlHxV9ZOYs6Y43yb7/l0= github.com/ipfs/go-fs-lock v0.0.1/go.mod h1:DNBekbboPKcxs1aukPSaOtFA3QfSdi5C855v0i9XJ8Y= +github.com/ipfs/go-graphsync v0.0.6-0.20200504202014-9d5f2c26a103 h1:SD+bXod/pOWKJCGj0tG140ht8Us5k+3JBcHw0PVYTho= +github.com/ipfs/go-graphsync v0.0.6-0.20200504202014-9d5f2c26a103/go.mod h1:jMXfqIEDFukLPZHqDPp8tJMbHO9Rmeb9CEGevngQbmE= github.com/ipfs/go-graphsync v0.0.6-0.20200708073926-caa872f68b2c h1:fCW8JzwvBMfODvdliK+s3ziYZPD/5FAzluahZYXVg3k= github.com/ipfs/go-graphsync v0.0.6-0.20200708073926-caa872f68b2c/go.mod h1:jMXfqIEDFukLPZHqDPp8tJMbHO9Rmeb9CEGevngQbmE= +github.com/ipfs/go-graphsync v0.0.6-0.20200715142715-e2f27c4754e6 h1:+dQnaRkLV4za46Gfw6b1KNVOCcGDrdnEGZrjz3kF80k= +github.com/ipfs/go-graphsync v0.0.6-0.20200715142715-e2f27c4754e6/go.mod h1:jMXfqIEDFukLPZHqDPp8tJMbHO9Rmeb9CEGevngQbmE= github.com/ipfs/go-hamt-ipld v0.0.15-0.20200131012125-dd88a59d3f2e/go.mod h1:9aQJu/i/TaRDW6jqB5U217dLIDopn50wxLdHXM2CTfE= github.com/ipfs/go-hamt-ipld v0.0.15-0.20200204200533-99b8553ef242/go.mod h1:kq3Pi+UP3oHhAdKexE+kHHYRKMoFNuGero0R7q3hWGg= github.com/ipfs/go-hamt-ipld v0.1.1-0.20200501020327-d53d20a7063e/go.mod h1:giiPqWYCnRBYpNTsJ/EX1ojldX5kTXrXYckSJQ7ko9M= @@ -671,6 +718,7 @@ github.com/jellevandenhooff/dkim v0.0.0-20150330215556-f50fe3d243e1/go.mod h1:E0 github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= +github.com/jmespath/go-jmespath v0.3.0/go.mod h1:9QtRXoHjLGCJ5IBSaohpXITPlowMeeYCZ7fLUTSywik= github.com/joeshaw/multierror v0.0.0-20140124173710-69b34d4ec901 h1:rp+c0RAYOWj8l6qbCUTSiRLG/iKnW3K3/QfPPuSsBt4= github.com/joeshaw/multierror v0.0.0-20140124173710-69b34d4ec901/go.mod h1:Z86h9688Y0wesXCyonoVr47MasHilkuLMqGhRZ4Hpak= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= @@ -727,6 +775,7 @@ github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= +github.com/lib/pq v1.7.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/libp2p/go-addr-util v0.0.1/go.mod h1:4ac6O7n9rIAKB1dnd+s8IbbMXkt+oBpzX4/+RACcnlQ= github.com/libp2p/go-addr-util v0.0.2 h1:7cWK5cdA5x72jX0g8iLrQWm5TRJZ6CzGdPEhWj7plWU= github.com/libp2p/go-addr-util v0.0.2/go.mod h1:Ecd6Fb3yIuLzq4bD7VcywcVSBtefcAwnUISBM3WG15E= @@ -757,6 +806,7 @@ github.com/libp2p/go-libp2p v0.6.0/go.mod h1:mfKWI7Soz3ABX+XEBR61lGbg+ewyMtJHVt0 github.com/libp2p/go-libp2p v0.6.1/go.mod h1:CTFnWXogryAHjXAKEbOf1OWY+VeAP3lDMZkfEI5sT54= github.com/libp2p/go-libp2p v0.7.0/go.mod h1:hZJf8txWeCduQRDC/WSqBGMxaTHCOYHt2xSU1ivxn0k= github.com/libp2p/go-libp2p v0.7.4/go.mod h1:oXsBlTLF1q7pxr+9w6lqzS1ILpyHsaBPniVO7zIHGMw= +github.com/libp2p/go-libp2p v0.8.1/go.mod h1:QRNH9pwdbEBpx5DTJYg+qxcVaDMAz3Ee/qDKwXujH5o= github.com/libp2p/go-libp2p v0.8.2/go.mod h1:NQDA/F/qArMHGe0J7sDScaKjW8Jh4y/ozQqBbYJ+BnA= github.com/libp2p/go-libp2p v0.8.3/go.mod h1:EsH1A+8yoWK+L4iKcbPYu6MPluZ+CHWI9El8cTaefiM= github.com/libp2p/go-libp2p v0.9.2/go.mod h1:cunHNLDVus66Ct9iXXcjKRLdmHdFdHVe1TAnbubJQqQ= @@ -859,6 +909,8 @@ github.com/libp2p/go-libp2p-net v0.0.2/go.mod h1:Yt3zgmlsHOgUWSXmt5V/Jpz9upuJBE8 github.com/libp2p/go-libp2p-netutil v0.0.1/go.mod h1:GdusFvujWZI9Vt0X5BKqwWWmZFxecf9Gt03cKxm2f/Q= github.com/libp2p/go-libp2p-netutil v0.1.0 h1:zscYDNVEcGxyUpMd0JReUZTrpMfia8PmLKcKF72EAMQ= github.com/libp2p/go-libp2p-netutil v0.1.0/go.mod h1:3Qv/aDqtMLTUyQeundkKsA+YCThNdbQD54k3TqjpbFU= +github.com/libp2p/go-libp2p-noise v0.1.1 h1:vqYQWvnIcHpIoWJKC7Al4D6Hgj0H012TuXRhPwSMGpQ= +github.com/libp2p/go-libp2p-noise v0.1.1/go.mod h1:QDFLdKX7nluB7DEnlVPbz7xlLHdwHFA9HiohJRr3vwM= github.com/libp2p/go-libp2p-peer v0.0.1/go.mod h1:nXQvOBbwVqoP+T5Y5nCjeH4sP9IX/J0AMzcDUVruVoo= github.com/libp2p/go-libp2p-peer v0.1.1/go.mod h1:jkF12jGB4Gk/IOo+yomm+7oLWxF278F7UnrYUQ1Q8es= github.com/libp2p/go-libp2p-peer v0.2.0 h1:EQ8kMjaCUwt/Y5uLgjT8iY2qg0mGUT0N1zUjer50DsY= @@ -1249,6 +1301,8 @@ github.com/prometheus/procfs v0.0.11/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4 github.com/prometheus/procfs v0.1.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.1.3 h1:F0+tqvhOksq22sc6iCHF5WGlWjdwj92p0udFh1VFBS8= github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= +github.com/raulk/clock v1.1.0 h1:dpb29+UKMbLqiU/jqIJptgLR1nn23HLgMY0sTCDza5Y= +github.com/raulk/clock v1.1.0/go.mod h1:3MpVxdZ/ODBQDxbN+kzshf5OSZwPjtMDx6BBXBmOeY0= github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0 h1:MkV+77GLUNo5oJ0jf870itWm3D0Sjh7+Za9gazKc5LQ= github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= @@ -1353,6 +1407,8 @@ github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpP github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA= github.com/testground/sdk-go v0.2.3-0.20200706132230-6a65ddac2d8c h1:TY0ghu3uY2SckyRvwSzzS0Am08KIX3ISeirp0riZLSw= github.com/testground/sdk-go v0.2.3-0.20200706132230-6a65ddac2d8c/go.mod h1:3ewI3dydDseP7eCO1MHGh+67simvbkcUnguPYssFqiA= +github.com/testground/sdk-go v0.2.3-0.20200716112730-420be929ef43 h1:KQQiKEzZYCsvU/XF+ppr5dTeYDWp38ckHT1iiqZV3/o= +github.com/testground/sdk-go v0.2.3-0.20200716112730-420be929ef43/go.mod h1:3ewI3dydDseP7eCO1MHGh+67simvbkcUnguPYssFqiA= github.com/texttheater/golang-levenshtein v0.0.0-20180516184445-d188e65d659e/go.mod h1:XDKHRm5ThF8YJjx001LtgelzsoaEcvnA7lVWz9EeX3g= github.com/tinylib/msgp v1.0.2/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE= github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= @@ -1815,6 +1871,7 @@ google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8 google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= google.golang.org/grpc v1.29.1 h1:EC2SB8S04d2r73uptxphDSUG+kTKVgjRPF+N3xpxRB4= google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= +google.golang.org/grpc/cmd/protoc-gen-go-grpc v0.0.0-20200617041141-9a465503579e/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= diff --git a/lotus-soup/init.go b/lotus-soup/init.go index c25d45eb..0fe54b2e 100644 --- a/lotus-soup/init.go +++ b/lotus-soup/init.go @@ -15,8 +15,8 @@ import ( ) func init() { - build.BlockDelaySecs = 2 - build.PropagationDelaySecs = 1 + // build.BlockDelaySecs = 2 + // build.PropagationDelaySecs = 1 _ = log.SetLogLevel("*", "WARN") _ = log.SetLogLevel("dht/RtRefreshManager", "ERROR") // noisy diff --git a/lotus-soup/main.go b/lotus-soup/main.go index a660a63c..fd6c6a8d 100644 --- a/lotus-soup/main.go +++ b/lotus-soup/main.go @@ -12,6 +12,7 @@ var cases = map[string]interface{}{ "deals-stress": testkit.WrapTestEnvironment(dealsStress), "drand-halting": testkit.WrapTestEnvironment(dealsE2E), "paych-stress": testkit.WrapTestEnvironment(paych.Stress), + "sync-mining": testkit.WrapTestEnvironment(syncMining), } func main() { diff --git a/lotus-soup/manifest.toml b/lotus-soup/manifest.toml index 38b9b87b..09fef907 100644 --- a/lotus-soup/manifest.toml +++ b/lotus-soup/manifest.toml @@ -151,3 +151,32 @@ instances = { min = 1, max = 100, default = 5 } # ********** Test-case specific ********** increments = { type = "int", default = "100", desc = "increments in which to send payment vouchers" } lane_count = { type = "int", default = "256", desc = "lanes to open; vouchers will be distributed across these lanes in round-robin fashion" } + + +[[testcases]] +name = "sync-mining" +instances = { min = 1, max = 100, default = 5 } + + [testcases.params] + clients = { type = "int", default = 1 } + miners = { type = "int", default = 1 } + balance = { type = "float", default = 1 } + sectors = { type = "int", default = 1 } + role = { type = "string" } + genesis_timestamp_offset = { type = "int", default = 0 } + + random_beacon_type = { type = "enum", default = "local-drand", options = ["mock", "local-drand", "external-drand"] } + + # Params relevant to drand nodes. drand nodes should have role="drand", and must all be + # in the same composition group. There must be at least threshold drand nodes. + # To get lotus nodes to actually use the drand nodes, you must set random_beacon_type="local-drand" + # for the lotus node groups. + drand_period = { type = "duration", default="10s" } + drand_threshold = { type = "int", default = 2 } + drand_gossip_relay = { type = "bool", default = true } + drand_log_level = { type = "string", default="info" } + suspend_events = { type = "string", default="", desc = "a sequence of halt/resume/wait events separated by '->'" } + + # Params relevant to pubsub tracing + enable_pubsub_tracer = { type = "bool", default = false } # Mining Mode: synchronized -vs- natural time + mining_mode = { type = "enum", default = "synchronized", options = ["synchronized", "natural"] } \ No newline at end of file diff --git a/lotus-soup/sync_mining.go b/lotus-soup/sync_mining.go new file mode 100644 index 00000000..9dffb896 --- /dev/null +++ b/lotus-soup/sync_mining.go @@ -0,0 +1,9 @@ +package main + +import ( + "github.com/filecoin-project/oni/lotus-soup/testkit" +) + +func syncMining(t *testkit.TestEnvironment) error { + return testkit.HandleDefaultRole(t) +} diff --git a/lotus-soup/testkit/lotus_opts.go b/lotus-soup/testkit/lotus_opts.go index 46df9078..aa86f0b2 100644 --- a/lotus-soup/testkit/lotus_opts.go +++ b/lotus-soup/testkit/lotus_opts.go @@ -3,12 +3,16 @@ package testkit import ( "fmt" + "github.com/filecoin-project/lotus/chain/store" "github.com/filecoin-project/lotus/node" "github.com/filecoin-project/lotus/node/config" "github.com/filecoin-project/lotus/node/modules" "github.com/filecoin-project/lotus/node/modules/dtypes" "github.com/filecoin-project/lotus/node/modules/lp2p" "github.com/filecoin-project/lotus/node/repo" + "github.com/filecoin-project/specs-actors/actors/runtime" + "github.com/prometheus/common/log" + "go.uber.org/fx" "github.com/libp2p/go-libp2p-core/peer" ma "github.com/multiformats/go-multiaddr" @@ -65,3 +69,15 @@ func withApiEndpoint(addr string) node.Option { return lr.SetAPIEndpoint(apima) }) } + +// withChainStore takes a double pointer to a ChainStore, creates a new +// ChainStore, and sets it under the pointer. +func withChainStore(cs **store.ChainStore) node.Option { + return node.Override(new(*store.ChainStore), func(_ fx.Lifecycle, bs dtypes.ChainBlockstore, ds dtypes.MetadataDS, syscalls runtime.Syscalls) *store.ChainStore { + *cs = store.NewChainStore(bs, ds, syscalls) + if err := (*cs).Load(); err != nil { + log.Warnf("loading chain state from disk: %s", err) + } + return *cs + }) +} diff --git a/lotus-soup/testkit/node.go b/lotus-soup/testkit/node.go index 4ce4d45a..b2ad3c8e 100644 --- a/lotus-soup/testkit/node.go +++ b/lotus-soup/testkit/node.go @@ -8,14 +8,17 @@ import ( "sort" "time" + "github.com/filecoin-project/go-address" "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/chain/beacon" + "github.com/filecoin-project/lotus/chain/store" "github.com/filecoin-project/lotus/chain/wallet" "github.com/filecoin-project/lotus/metrics" "github.com/filecoin-project/lotus/node" "github.com/filecoin-project/lotus/node/modules/dtypes" modtest "github.com/filecoin-project/lotus/node/modules/testing" tstats "github.com/filecoin-project/lotus/tools/stats" + "github.com/raulk/clock" "github.com/kpacha/opencensus-influxdb" ma "github.com/multiformats/go-multiaddr" @@ -26,12 +29,24 @@ import ( var PrepareNodeTimeout = time.Minute +const ( + AddressWallet = iota + AddressMinerActor + AddressMinerID + AddressMinerWorker +) + type LotusNode struct { - FullApi api.FullNode - MinerApi api.StorageMiner - StopFn node.StopFunc - Wallet *wallet.Key - MineOne func(context.Context, func(bool, error)) error + t *TestEnvironment + + FullApi api.FullNode + MinerApi api.StorageMiner + Addresses [4]address.Address // indexed by Address* constants. + StopFn node.StopFunc + ChainStore *store.ChainStore + Wallet *wallet.Key + MockClock *clock.Mock + MineOne func(context.Context, func(bool, error)) error } func (n *LotusNode) setWallet(ctx context.Context, walletKey *wallet.Key) error { @@ -46,6 +61,7 @@ func (n *LotusNode) setWallet(ctx context.Context, walletKey *wallet.Key) error } n.Wallet = walletKey + n.Addresses[AddressWallet] = walletKey.Address return nil } diff --git a/lotus-soup/testkit/node_time.go b/lotus-soup/testkit/node_time.go new file mode 100644 index 00000000..fe8decbb --- /dev/null +++ b/lotus-soup/testkit/node_time.go @@ -0,0 +1,120 @@ +package testkit + +import ( + "context" + "fmt" + "time" + + "github.com/filecoin-project/lotus/build" + "github.com/filecoin-project/specs-actors/actors/abi" + "github.com/raulk/clock" + "github.com/testground/sdk-go/sync" +) + +// ClockSyncTopic is the topic where clock synchronization events are exchanged. +var ClockSyncTopic = sync.NewTopic("clock_sync", &ClockSyncMsg{}) + +// ClockSyncMsg is a clock synchronization message. +type ClockSyncMsg struct { + ID string // ${groupname}_${groupseq} + Epoch abi.ChainEpoch +} + +// SynchronizeClock synchronizes this instance's clock with the clocks of all +// miner and client nodes participating in this test scenario. +// +// This function returns two channels. +// +// The first channel (localAdvance) is where the user requests local advancement +// to the next epoch. Such requests likely originate from some local event that +// implies readiness to advance, such as "mining round completed" events from +// synchronized mining. Upon receiving a local advance signal, the control +// goroutine forwards the local clock by build.BlockDelaySecs, thus progressing +// one chain epoch. It then signals this fact to all other nodes participating +// in the test via the Testground synchronization service. +// +// The second channel is where the global clock synchronizer signals every time +// the entirety of test participants have progressed to the next epoch, thus +// indicating that all nodes are eady to commence that chain epoch of +// computation. +// +// Essentially this behaviour can be assimilated to a distributed sempaphore. +// +// This method will return immediately, and will spawn a background goroutine +// that performs the clock synchronisation work. +func (n *LotusNode) SynchronizeClock(ctx context.Context) (localAdvance chan<- abi.ChainEpoch, globalEpoch <-chan abi.ChainEpoch, err error) { + n.MockClock = clock.NewMock() + build.Clock = n.MockClock + + gen, err := n.FullApi.ChainGetGenesis(context.Background()) + if err != nil { + return nil, nil, fmt.Errorf("failed to get genesis: %w", err) + } + + // start at genesis. + genesisTime := time.Unix(int64(gen.MinTimestamp()), 0) + n.MockClock.Set(genesisTime) + + var ( + localEpochAdvanceCh = make(chan abi.ChainEpoch, 128) + globalEpochStartCh = make(chan abi.ChainEpoch, 128) + ) + + // jumpstart the clock! + localEpochAdvanceCh <- abi.ChainEpoch(1) + + var ( + id = fmt.Sprintf("%s_%d", n.t.TestGroupID, n.t.GroupSeq) + + minerCnt = n.t.IntParam("miners") + clientCnt = n.t.IntParam("clients") + totalCnt = minerCnt + clientCnt + + epoch = abi.ChainEpoch(0) // current epoch: genesis + epochInterval = time.Duration(build.BlockDelaySecs) * time.Second + + // ready tracks which nodes have advanced to the next round. + // when all nodes have advanced, we tick the global clock and reset + // this slice. + ready []string + + signalCh = make(chan *ClockSyncMsg, 128) + sub = n.t.SyncClient.MustSubscribe(ctx, ClockSyncTopic, signalCh) + ) + + go func() { + defer close(globalEpochStartCh) + + for { + select { + case <-localEpochAdvanceCh: + // move the local clock forward, and announce that fact to all other instances. + n.MockClock.Add(epochInterval) + epoch++ + n.t.RecordMessage("advanced local clock: %v [epoch=%d]", n.MockClock.Now(), epoch) + n.t.SyncClient.MustPublish(ctx, ClockSyncTopic, &ClockSyncMsg{ + ID: id, + Epoch: epoch, + }) + + case s := <-signalCh: + // this is a clock event from another instance (or ourselves). + ready = append(ready, s.ID) + if len(ready) != totalCnt { + continue + } + // release the new epoch and reset the state. + globalEpochStartCh <- epoch + ready = ready[0:0] + + case <-ctx.Done(): + return + + case <-sub.Done(): + panic("global clock synchronization subscription died") + } + } + }() + + return localEpochAdvanceCh, globalEpochStartCh, nil +} diff --git a/lotus-soup/testkit/retrieval.go b/lotus-soup/testkit/retrieval.go index 215091ec..c245d5cf 100644 --- a/lotus-soup/testkit/retrieval.go +++ b/lotus-soup/testkit/retrieval.go @@ -21,7 +21,7 @@ import ( func RetrieveData(t *TestEnvironment, ctx context.Context, client api.FullNode, fcid cid.Cid, carExport bool, data []byte) { t1 := time.Now() - offers, err := client.ClientFindData(ctx, fcid) + offers, err := client.ClientFindData(ctx, fcid, nil) if err != nil { panic(err) } diff --git a/lotus-soup/testkit/role_bootstrapper.go b/lotus-soup/testkit/role_bootstrapper.go index 39d5dba5..6bab1d52 100644 --- a/lotus-soup/testkit/role_bootstrapper.go +++ b/lotus-soup/testkit/role_bootstrapper.go @@ -92,10 +92,12 @@ func PrepareBootstrapper(t *TestEnvironment) (*Bootstrapper, error) { genesisMiners = append(genesisMiners, pm.Miner) } + genesisTimestamp := uint64(time.Now().Unix()) - uint64(t.IntParam("genesis_timestamp_offset")) + genesisTemplate := genesis.Template{ Accounts: genesisActors, Miners: genesisMiners, - Timestamp: uint64(time.Now().Unix()) - uint64(t.IntParam("genesis_timestamp_offset")), // this needs to be in the past + Timestamp: genesisTimestamp, } // dump the genesis block @@ -114,7 +116,7 @@ func PrepareBootstrapper(t *TestEnvironment) (*Bootstrapper, error) { bootstrapperIP := t.NetClient.MustGetDataNetworkIP().String() - n := &LotusNode{} + n := &LotusNode{t: t} stop, err := node.New(context.Background(), node.FullAPI(&n.FullApi), node.Online(), @@ -138,6 +140,7 @@ func PrepareBootstrapper(t *TestEnvironment) (*Bootstrapper, error) { stop(context.TODO()) return nil, err } + for _, a := range bootstrapperAddrs.Addrs { ip, err := a.ValueForProtocol(ma.P_IP4) if err != nil { @@ -162,8 +165,9 @@ func PrepareBootstrapper(t *TestEnvironment) (*Bootstrapper, error) { } genesisMsg := &GenesisMsg{ - Genesis: genesisBuffer.Bytes(), - Bootstrapper: bootstrapperAddr.Bytes(), + Genesis: genesisBuffer.Bytes(), + Bootstrapper: bootstrapperAddr.Bytes(), + TimestampUnix: genesisTimestamp, } t.SyncClient.MustPublish(ctx, GenesisTopic, genesisMsg) diff --git a/lotus-soup/testkit/role_client.go b/lotus-soup/testkit/role_client.go index f26c2064..738e53e6 100644 --- a/lotus-soup/testkit/role_client.go +++ b/lotus-soup/testkit/role_client.go @@ -60,7 +60,7 @@ func PrepareClient(t *TestEnvironment) (*LotusClient, error) { nodeRepo := repo.NewMemory(nil) // create the node - n := &LotusNode{} + n := &LotusNode{t: t} stop, err := node.New(context.Background(), node.FullAPI(&n.FullApi), node.Online(), @@ -113,7 +113,7 @@ func PrepareClient(t *TestEnvironment) (*LotusClient, error) { // densely connect the client to the full node and the miners themselves. for _, miner := range addrs { - if err := n.FullApi.NetConnect(ctx, miner.FullNetAddrs); err != nil { + if err := n.FullApi.NetConnect(ctx, miner.WorkerNetAddrs); err != nil { return nil, fmt.Errorf("client failed to connect to full node of miner: %w", err) } if err := n.FullApi.NetConnect(ctx, miner.MinerNetAddrs); err != nil { @@ -140,6 +140,23 @@ func PrepareClient(t *TestEnvironment) (*LotusClient, error) { } func (c *LotusClient) RunDefault() error { + // if we're running in synchronized mining, enroll this client + // in the global clock. + if c.t.StringParam("mining_mode") == "synchronized" { + localAdvanceCh, globalEpochCh, err := c.SynchronizeClock(context.Background()) + if err != nil { + return fmt.Errorf("failed to initiate clock synchronizer: %w", err) + } + + go func() { + // for now, clients are always one epoch ahead locally with regards to miners. + // keeping the flywheel spinning! + for epoch := range globalEpochCh { + localAdvanceCh <- epoch + 1 + } + }() + } + // run forever c.t.RecordMessage("running default client forever") c.t.WaitUntilAllDone() diff --git a/lotus-soup/testkit/role_miner.go b/lotus-soup/testkit/role_miner.go index 204b3a40..0732c225 100644 --- a/lotus-soup/testkit/role_miner.go +++ b/lotus-soup/testkit/role_miner.go @@ -8,16 +8,11 @@ import ( "net/http" "time" - "contrib.go.opencensus.io/exporter/prometheus" - "github.com/filecoin-project/go-address" - "github.com/filecoin-project/go-jsonrpc" - "github.com/filecoin-project/go-jsonrpc/auth" - "github.com/filecoin-project/go-storedcounter" "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/api/apistruct" "github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/chain/actors" - genesis_chain "github.com/filecoin-project/lotus/chain/gen/genesis" + "github.com/filecoin-project/lotus/chain/gen/genesis" "github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/wallet" "github.com/filecoin-project/lotus/cmd/lotus-seed/seed" @@ -26,15 +21,23 @@ import ( "github.com/filecoin-project/lotus/node/impl" "github.com/filecoin-project/lotus/node/modules" "github.com/filecoin-project/lotus/node/repo" + "github.com/filecoin-project/specs-actors/actors/abi" "github.com/filecoin-project/specs-actors/actors/builtin" saminer "github.com/filecoin-project/specs-actors/actors/builtin/miner" "github.com/filecoin-project/specs-actors/actors/crypto" + + "github.com/filecoin-project/go-address" + "github.com/filecoin-project/go-jsonrpc" + "github.com/filecoin-project/go-jsonrpc/auth" + "github.com/filecoin-project/go-storedcounter" + + "contrib.go.opencensus.io/exporter/prometheus" "github.com/gorilla/mux" + "github.com/hashicorp/go-multierror" "github.com/ipfs/go-datastore" libp2pcrypto "github.com/libp2p/go-libp2p-core/crypto" "github.com/libp2p/go-libp2p-core/peer" - "github.com/testground/sdk-go/sync" ) const ( @@ -43,11 +46,16 @@ const ( type LotusMiner struct { *LotusNode - - t *TestEnvironment } func PrepareMiner(t *TestEnvironment) (*LotusMiner, error) { + var ( + balance = t.FloatParam("balance") + sectors = t.IntParam("sectors") + minerCnt = t.IntParam("miners") + miningMode = t.StringParam("mining_mode") + ) + ctx, cancel := context.WithTimeout(context.Background(), PrepareNodeTimeout) defer cancel() @@ -68,9 +76,9 @@ func PrepareMiner(t *TestEnvironment) (*LotusMiner, error) { } // publish the account ID/balance - balance := t.FloatParam("balance") + balanceMsg := &InitialBalanceMsg{Addr: walletKey.Address, Balance: balance} - t.SyncClient.Publish(ctx, BalanceTopic, balanceMsg) + t.SyncClient.MustPublish(ctx, BalanceTopic, balanceMsg) // create and publish the preseal commitment priv, _, err := libp2pcrypto.GenerateEd25519Key(rand.Reader) @@ -84,9 +92,9 @@ func PrepareMiner(t *TestEnvironment) (*LotusMiner, error) { } // pick unique sequence number for each miner, no matter in which group they are - seq := t.SyncClient.MustSignalAndWait(ctx, StateMinerPickSeqNum, t.IntParam("miners")) + seq := t.SyncClient.MustSignalAndWait(ctx, StateMinerPickSeqNum, minerCnt) - minerAddr, err := address.NewIDAddress(genesis_chain.MinerStart + uint64(seq-1)) + minerAddr, err := address.NewIDAddress(genesis.MinerStart + uint64(seq-1)) if err != nil { return nil, err } @@ -96,7 +104,6 @@ func PrepareMiner(t *TestEnvironment) (*LotusMiner, error) { return nil, err } - sectors := t.IntParam("sectors") genMiner, _, err := seed.PreSeal(minerAddr, abi.RegisteredSealProof_StackedDrg2KiBV1, 0, sectors, presealDir, []byte("TODO: randomize this"), &walletKey.KeyInfo, false) if err != nil { return nil, err @@ -106,7 +113,7 @@ func PrepareMiner(t *TestEnvironment) (*LotusMiner, error) { t.RecordMessage("Miner Info: Owner: %s Worker: %s", genMiner.Owner, genMiner.Worker) presealMsg := &PresealMsg{Miner: *genMiner, Seqno: seq} - t.SyncClient.Publish(ctx, PresealTopic, presealMsg) + t.SyncClient.MustPublish(ctx, PresealTopic, presealMsg) // then collect the genesis block and bootstrapper address genesisMsg, err := WaitForGenesis(t, ctx) @@ -167,7 +174,7 @@ func PrepareMiner(t *TestEnvironment) (*LotusMiner, error) { // create the node // we need both a full node _and_ and storage miner node - n := &LotusNode{} + n := &LotusNode{t: t} nodeRepo := repo.NewMemory(nil) @@ -180,6 +187,7 @@ func PrepareMiner(t *TestEnvironment) (*LotusMiner, error) { withListenAddress(minerIP), withBootstrapper(genesisMsg.Bootstrapper), withPubsubConfig(false, pubsubTracer), + withChainStore(&n.ChainStore), drandOpt, ) if err != nil { @@ -189,10 +197,12 @@ func PrepareMiner(t *TestEnvironment) (*LotusMiner, error) { // set the wallet err = n.setWallet(ctx, walletKey) if err != nil { - stop1(context.TODO()) + _ = stop1(context.TODO()) return nil, err } + m := &LotusMiner{LotusNode: n} + minerOpts := []node.Option{ node.StorageMiner(&n.MinerApi), node.Online(), @@ -202,10 +212,11 @@ func PrepareMiner(t *TestEnvironment) (*LotusMiner, error) { withMinerListenAddress(minerIP), } - if t.StringParam("mining_mode") != "natural" { + if miningMode != "natural" { mineBlock := make(chan func(bool, error)) minerOpts = append(minerOpts, - node.Override(new(*miner.Miner), miner.NewTestMiner(mineBlock, minerAddr))) + node.Override(new(*miner.Miner), miner.NewTestMiner(mineBlock, minerAddr)), + ) n.MineOne = func(ctx context.Context, cb func(bool, error)) error { select { @@ -219,17 +230,15 @@ func PrepareMiner(t *TestEnvironment) (*LotusMiner, error) { stop2, err := node.New(context.Background(), minerOpts...) if err != nil { - stop1(context.TODO()) + _ = stop1(context.TODO()) return nil, err } + n.StopFn = func(ctx context.Context) error { - // TODO use a multierror for this - err2 := stop2(ctx) - err1 := stop1(ctx) - if err2 != nil { - return err2 - } - return err1 + var err *multierror.Error + err = multierror.Append(stop2(ctx)) + err = multierror.Append(stop1(ctx)) + return err.ErrorOrNil() } registerAndExportMetrics(minerAddr.String()) @@ -240,16 +249,11 @@ func PrepareMiner(t *TestEnvironment) (*LotusMiner, error) { } // Start listening on the full node. - fullNodeNetAddrs, err := n.FullApi.NetAddrsListen(ctx) + workerNetAddrs, err := n.FullApi.NetAddrsListen(ctx) if err != nil { panic(err) } - // err = n.MinerApi.NetConnect(ctx, fullNodeNetAddrs) - // if err != nil { - // panic(err) - // } - // set seal delay to lower value than 1 hour err = n.MinerApi.SectorSetSealDelay(ctx, sealDelay) if err != nil { @@ -267,7 +271,7 @@ func PrepareMiner(t *TestEnvironment) (*LotusMiner, error) { // add local storage for presealed sectors err = n.MinerApi.StorageAddLocal(ctx, presealDir) if err != nil { - n.StopFn(context.TODO()) + _ = n.StopFn(context.TODO()) return nil, err } @@ -278,8 +282,8 @@ func PrepareMiner(t *TestEnvironment) (*LotusMiner, error) { } changeMinerID := &types.Message{ - To: minerAddr, From: genMiner.Worker, + To: minerAddr, Method: builtin.MethodsMiner.ChangePeerID, Params: minerIDEncoded, Value: types.NewInt(0), @@ -289,7 +293,7 @@ func PrepareMiner(t *TestEnvironment) (*LotusMiner, error) { _, err = n.FullApi.MpoolPushMessage(ctx, changeMinerID) if err != nil { - n.StopFn(context.TODO()) + _ = n.StopFn(context.TODO()) return nil, err } @@ -299,13 +303,17 @@ func PrepareMiner(t *TestEnvironment) (*LotusMiner, error) { return nil, err } + n.Addresses[AddressMinerWorker] = genMiner.Worker + n.Addresses[AddressMinerID] = minerAddr + n.Addresses[AddressMinerActor] = minerActor + minerNetAddrs, err := n.MinerApi.NetAddrsListen(ctx) if err != nil { return nil, err } t.SyncClient.MustPublish(ctx, MinersAddrsTopic, MinerAddressesMsg{ - FullNetAddrs: fullNodeNetAddrs, + WorkerNetAddrs: workerNetAddrs, MinerNetAddrs: minerNetAddrs, MinerActorAddr: minerActor, }) @@ -317,31 +325,29 @@ func PrepareMiner(t *TestEnvironment) (*LotusMiner, error) { sctx, cancel := context.WithCancel(ctx) defer cancel() t.SyncClient.MustSubscribe(sctx, MinersAddrsTopic, minerCh) - for i := 0; i < t.IntParam("miners"); i++ { + for i := 0; i < minerCnt; i++ { m := <-minerCh if m.MinerActorAddr == minerActor { // once I find myself, I stop connecting to others, to avoid a simopen problem. break } - err := n.FullApi.NetConnect(ctx, m.FullNetAddrs) + err := n.FullApi.NetConnect(ctx, m.WorkerNetAddrs) if err != nil { - return nil, fmt.Errorf("failed to connect to miner %s on: %v", m.MinerActorAddr, m.FullNetAddrs) + return nil, fmt.Errorf("failed to connect to miner %s on: %v", m.MinerActorAddr, m.WorkerNetAddrs) } - t.RecordMessage("connected to full node of miner %s on %v", m.MinerActorAddr, m.FullNetAddrs) + t.RecordMessage("connected to full node of miner %s on %v", m.MinerActorAddr, m.WorkerNetAddrs) } t.RecordMessage("waiting for all nodes to be ready") t.SyncClient.MustSignalAndWait(ctx, StateReady, t.TestInstanceCount) - m := &LotusMiner{n, t} - err = startFullNodeAPIServer(t, nodeRepo, n.FullApi) if err != nil { return nil, err } - err = startStorageMinerAPIServer(t, minerRepo, n.MinerApi) + err = m.startStorageMinerAPIServer(t, minerRepo, n.MinerApi) if err != nil { return nil, err } @@ -353,86 +359,39 @@ func (m *LotusMiner) RunDefault() error { var ( t = m.t clients = t.IntParam("clients") - miners = t.IntParam("miners") ) t.RecordMessage("running miner") - t.RecordMessage("block delay: %v", build.BlockDelaySecs) t.D().Gauge("miner.block-delay").Update(float64(build.BlockDelaySecs)) ctx := context.Background() - myActorAddr, err := m.MinerApi.ActorAddress(ctx) - if err != nil { - return err - } // mine / stop mining - mine := true done := make(chan struct{}) - if m.MineOne != nil { - go func() { - defer t.RecordMessage("shutting down mining") - defer close(done) - - var i int - for i = 0; mine; i++ { - // synchronize all miners to mine the next block - t.RecordMessage("synchronizing all miners to mine next block [%d]", i) - stateMineNext := sync.State(fmt.Sprintf("mine-block-%d", i)) - t.SyncClient.MustSignalAndWait(ctx, stateMineNext, miners) - - ch := make(chan error) - const maxRetries = 100 - success := false - for retries := 0; retries < maxRetries; retries++ { - err := m.MineOne(ctx, func(mined bool, err error) { - if mined { - t.D().Counter(fmt.Sprintf("block.mine,miner=%s", myActorAddr)).Inc(1) - } - ch <- err - }) - if err != nil { - panic(err) - } - - miningErr := <-ch - if miningErr == nil { - success = true - break - } - t.D().Counter("block.mine.err").Inc(1) - t.RecordMessage("retrying block [%d] after %d attempts due to mining error: %s", - i, retries, miningErr) - } - if !success { - panic(fmt.Errorf("failed to mine block %d after %d retries", i, maxRetries)) - } - } - - // signal the last block to make sure no miners are left stuck waiting for the next block signal - // while the others have stopped - stateMineLast := sync.State(fmt.Sprintf("mine-block-%d", i)) - t.SyncClient.MustSignalEntry(ctx, stateMineLast) - }() + if t.StringParam("mining_mode") != "natural" { + localAdvanceCh, globalEpochCh, err := m.SynchronizeClock(context.Background()) + if err != nil { + return fmt.Errorf("failed to initiate clock synchronizer: %w", err) + } + go m.SynchronizeMiner(context.Background(), globalEpochCh, localAdvanceCh) } else { close(done) } // wait for a signal from all clients to stop mining - err = <-t.SyncClient.MustBarrier(ctx, StateStopMining, clients).C + err := <-t.SyncClient.MustBarrier(ctx, StateStopMining, clients).C if err != nil { return err } - mine = false <-done t.SyncClient.MustSignalAndWait(ctx, StateDone, t.TestInstanceCount) return nil } -func startStorageMinerAPIServer(t *TestEnvironment, repo *repo.MemRepo, minerApi api.StorageMiner) error { +func (m *LotusMiner) startStorageMinerAPIServer(t *TestEnvironment, repo *repo.MemRepo, minerApi api.StorageMiner) error { mux := mux.NewRouter() rpcServer := jsonrpc.NewServer() diff --git a/lotus-soup/testkit/role_miner_sync.go b/lotus-soup/testkit/role_miner_sync.go new file mode 100644 index 00000000..e0ad9a83 --- /dev/null +++ b/lotus-soup/testkit/role_miner_sync.go @@ -0,0 +1,185 @@ +package testkit + +import ( + "context" + "fmt" + + "github.com/filecoin-project/go-address" + "github.com/filecoin-project/specs-actors/actors/abi" + "github.com/testground/sdk-go/run" + "github.com/testground/sdk-go/sync" +) + +// MinerSyncTopic is the topic where miner events are exchanged. +var MinerSyncTopic = sync.NewTopic("miner_sync", &MiningSyncMsg{}) + +// MiningSyncMsg signals that the miner attempted to mine in a particular epoch, +// indicating whether it produced a block or not. +type MiningSyncMsg struct { + // Addr is the address of the miner. + Addr address.Address + // Produced signals whether the miner produced a block or not. + Produced bool +} + +// SynchronizeMiner synchronizes this miner with all other miners in this test, +// so that they're mining in perfect synchrony according to a globally- +// synchronized epoch clock. +// +// This function _receives_ "epoch start" signals and _emits_ "epoch end" +// signals: +// +// * an epoch start signal attempts to locally mine a block, and publishes +// a message on a sync topic indicating that we're done mining, and whether +// we produced a block or not. +// * all miners wait until their HEAD advances to the tipset that includes +// all blocks that were produced in this epoch. +// * once that happens, we emit an epoch end signal, which the caller can +// interpret as a signal to advance the clock and begin a new epoch. +func (m *LotusMiner) SynchronizeMiner(ctx context.Context, mineTrigger <-chan abi.ChainEpoch, mineDone chan<- abi.ChainEpoch) { + defer run.HandlePanics() + defer m.t.RecordMessage("shutting down mining") + + var ( + epoch = abi.ChainEpoch(0) + + minerCnt = m.t.IntParam("miners") + // done tracks the miners that are done producing a block in this epoch. + done []address.Address + // produced indexes the miners that produced a block in this epoch. + produced = make(map[address.Address]struct{}, minerCnt) + + signalCh = make(chan *MiningSyncMsg, 128) + sub = m.t.SyncClient.MustSubscribe(ctx, MinerSyncTopic, signalCh) + ) + + for { + select { + case e := <-mineTrigger: + m.t.RecordMessage("epoch started: %d; mining", e) + epoch = e + + produced, err := m.mineRound(ctx, epoch) + if err != nil { + panic(err) + } + + m.t.SyncClient.MustPublish(ctx, MinerSyncTopic, &MiningSyncMsg{ + Addr: m.Addresses[AddressMinerActor], + Produced: produced, + }) + + case s := <-signalCh: + // this is a signal that a miner is done mining. + done = append(done, s.Addr) + if s.Produced { + produced[s.Addr] = struct{}{} + } + + if len(done) != minerCnt { + // still waiting for other miners. + continue + } + + // we've now ascertained that all miners have reported. + // + // if this is a null round, wait for no HEAD changes. + // otherwise, we wait for blocks to propagate and for our HEAD + // to progress to a tipset that contains the blocks from all + // miners that produced a block, at the chain height we expect. + if len(produced) > 0 { + err := m.waitForHeadUpdate(ctx, epoch, produced) + if err != nil { + panic(err) + } + } + + // reset state in preparation for next round. + done = done[0:0] + for k := range produced { + delete(produced, k) + } + + // signal epoch end and loop over. + mineDone <- epoch + + case <-ctx.Done(): + return + + case <-sub.Done(): + panic("mining synchronization subscription died") + } + } +} + +func (m *LotusMiner) waitForHeadUpdate(ctx context.Context, epoch abi.ChainEpoch, blockProducers map[address.Address]struct{}) error { + ctx, cancel := context.WithCancel(context.Background()) + changes := m.ChainStore.SubHeadChanges(ctx) + defer cancel() + + for { + select { + case change := <-changes: + Change: + for _, c := range change { + if c.Val.Height() != epoch { + continue // not the epoch we're seeking. + } + blocks := c.Val.Blocks() + if len(blocks) != len(blockProducers) { + continue // this tipset still doesn't include all mined blocks. + } + for _, b := range blocks { + if _, ok := blockProducers[b.Miner]; !ok { + continue Change // not the HEAD we're looking for. + } + } + // the HEAD tipset includes all blocks mined in this round; we're done! + return nil + } + + case <-ctx.Done(): + return fmt.Errorf("synchronizing mining: gave up while awaiting expected head update for epoch %d: %w", epoch, ctx.Err()) + } + } +} + +// mineRound attempts to mine a round. Apparently mining can fail sporadically: +// https://github.com/filecoin-project/lotus/pull/2259, so we perform 100 +// attempts before giving up entirely. +func (m *LotusMiner) mineRound(ctx context.Context, epoch abi.ChainEpoch) (produced bool, err error) { + const retries = 100 + for attempt := 0; attempt < retries; attempt++ { + var ( + produced bool + err error + done = make(chan struct{}) + ) + + err = m.MineOne(ctx, func(m bool, e error) { + produced, err = m, e + close(done) + }) + if err != nil { + // this is a serious error, we didn't even attempt to mine a block; abort. + return false, fmt.Errorf("failed to trigger mining a block: %w", err) + } + <-done + + if err != nil { + // mining failed. + m.t.D().Counter("block.mine.err").Inc(1) + m.t.RecordMessage("retrying block at height %d after %d attempts due to mining error: %s", epoch, attempt, err) + continue + } + + // all ok, mining completed. + m.t.RecordMessage("~~~ mining completed! did we produce a block at epoch %d? %t ~~~", epoch, produced) + if produced { + m.t.D().Counter(fmt.Sprintf("block.mine,miner=%s", m.Addresses[AddressMinerActor])).Inc(1) + } + return produced, nil + } + + return false, fmt.Errorf("failed to mine a block after %d retries", retries) +} diff --git a/lotus-soup/testkit/sync.go b/lotus-soup/testkit/sync.go index 51975ce2..cd436bcb 100644 --- a/lotus-soup/testkit/sync.go +++ b/lotus-soup/testkit/sync.go @@ -36,8 +36,9 @@ type PresealMsg struct { } type GenesisMsg struct { - Genesis []byte - Bootstrapper []byte + Genesis []byte + Bootstrapper []byte + TimestampUnix uint64 } type ClientAddressesMsg struct { @@ -46,7 +47,7 @@ type ClientAddressesMsg struct { } type MinerAddressesMsg struct { - FullNetAddrs peer.AddrInfo + WorkerNetAddrs peer.AddrInfo MinerNetAddrs peer.AddrInfo MinerActorAddr address.Address }