Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

replace freezer with a custom implementation #103

Closed
wants to merge 180 commits into from
Closed

Conversation

zcstarr
Copy link
Contributor

@zcstarr zcstarr commented May 20, 2020

…mplementation that's toggled by flag

@zcstarr zcstarr requested a review from meowsbits May 20, 2020 17:16
@zcstarr
Copy link
Contributor Author

zcstarr commented May 20, 2020

This is just a dummy PR just so we can quickly look at the code and diff it as we work out what's the best approach to adding a more generic and flexible thing to "servicize or decouple" the freezer

@meowsbits meowsbits marked this pull request as draft May 20, 2020 18:25
@meowsbits meowsbits changed the title feat(test): a test pipeline that replaces the freezer with a custom i… replace freezer with a custom implementation May 20, 2020
@meowsbits
Copy link
Member

@zcstarr 🚧 Just rebased on master, --force pushed.

@meowsbits
Copy link
Member

meowsbits commented May 22, 2020

Just pushed changes which sketch adding support for AWS S3 as the remote freezer.

You'll need to have your AWS SDK credentials set (https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html). In the script below I have creds as:

cat ~/.aws/credentials
[developer-s3]
aws_access_key_id = AKxxx
aws_secret_access_key = Dsxxx

Note the CLI flag change, now with --datadir.ancient.remote=s3.

env AWS_PROFILE=developer-s3 AWS_REGION=us-east-1 ./build/bin/geth \
  --classic \
  --ipcpath=~/.ethereum/geth.ipc \
  --datadir ~/SAMSUNG_T5/e/sandbox/remote-freezer-develop \
  --verbosity 4 \
  --datadir.ancient.remote=s3 \
  --datadir.ancient.remote.namespace=coregeth-classic-cataclysm |& tee geth.log

NOTE: S3 demands that bucket names are globally unique. So you'll need to change coregeth-classic-cataclysm to be your own special snowflake.


It currently stores the RLP encoded blobs in S3 buckets per "table", eg. bodies, headers, etc. Bucket names are structured as <chainID>-<genesisHash[:8]>-<tableName>, with the block information being stored by number with an rlp extension, eg. 1.rlp. An ugly index-marker is also persisted on S3 that (sketchily) represents the number of frozen items. Index marking and metadata in general will want to be thought through and should for now be understood as a TODO.

Eventually caching will be critical for performance, since Sync() is designed to do the heavy lifting (eg flushing to disk) and is called accordingly, but right now AppendAncient and Truncate are directly writing, and reads are likewise done in sync.

@meowsbits
Copy link
Member

meowsbits commented May 22, 2020

To nuke your buckets between development versions:

> cat ./geth-s3-buckets-nuke.sh
#!/usr/bin/env bash

env AWS_PROFILE=developer-s3 AWS_REGION=us-east-1 aws s3 rb s3://<my-bucket> --force

@meowsbits
Copy link
Member

meowsbits commented Jun 5, 2020

A few thoughts.

Features for S3 as-is:

  • Fix: use just one bucket. By default, S3 accounts are limited to 100 buckets.
  • Retroactive upload. "I have already synced. I want to use the remote ancient store without syncing all over again."
  • Read-only remote. "I already have one instance using remote ancients. I want to allow another instance to use the same remote ancient store, and it's ok if it's a slave."
  • Configurable bucket settings. "I don't want to use the default bucket name and/or region."
  • Maybe just store entities in JSON? "I want to use my data elsewhere without a lot of hullabaloo."
  • Maybe (optionally) compress the data? "I want to use ancients, but would prefer spending $0.76/month instead of $1.11"

Extensibility-oriented:

  • Create an RPC server+client (in place of|congruent to) the S3 implementation. It handles subscriptions only (via websockets and unix sockets) and pushes events for write events/methods (eg. AppendAncient, Sync) and manages requests for read methods (eg. Ancient, HasAncient) as well. Now you can write your own standalone remote ancient service.

@meowsbits
Copy link
Member

meowsbits commented Jun 9, 2020

So, as-is with the current schema, which adheres strictly to the freezerTable schema (hashes, headers, bodies...) and uses block number as the index, I'm seeing about 2 blocks/second upload, which will take about 2 months to upload for the classic chain's current height. Further, creating 50million relatively tiny objects may have negative implications for the S3 request costs, where I expect fewer, larger objects will be cheaper.

IMO this is beyond usable for most cases, so we need to find a way to make uploads more efficient.

My understanding so far is that most of our upload time is due to transaction overhead (even though we're batching uploads by up to 2048 blocks). The upside of block/kind-atomic resources is that we get to download on-demand just what we need, which, in my experience trying out the JS console eth.getBlock for remote blocks is "fast" as-is (barely noticeable difference from local FS).

Grouping resources by block (instead of by kind/block) saw about 8 blocks/second upload. I'm going to try reverting to this pattern, but then extending it further to use 32-block objects, with each containing all the tables. If this moves the upload time from 2 blocks/second to 2*4*32 = 256 blocks/second then I'm going to call that good enough. The downside is that download will take longer, and will download stuff that isn't necessary.

There is probably a further way of managing this by using an AWS Lambda to partition or group the objects once they're uploaded, but I'm going to call that out-of-scope for now.

As-is:

2020-06-08-211829_771x684_screenshot
2020-06-08-211855_764x994_screenshot

@meowsbits
Copy link
Member

image

@meowsbits
Copy link
Member

image

@meowsbits
Copy link
Member

Just thinking out loud here. I'm coming back to 1 block objects. This keeps GETs streamlined. Will cost about 50USD at the without-any-batching ceiling to set up (upload entire ancient store), mostly in transaction counts. Batching requests in 2048-block chunks (normal during sync) will bring the number down to 10M / 2048 =~ 5k, costing just a few cents in PUT requests.

The downside still is time, where I'm estimating 2-3 weeks for an upload-enabled sync. Although I'd consider this on the upper end of desirable, I'm currently of the opinion that it is tolerable. Once a user has a canonical bucket uploaded, they can use s3 sync to copy entire buckets.

@zcstarr
Copy link
Contributor Author

zcstarr commented Jun 10, 2020

This is awesome,

So, as-is with the current schema, which adheres strictly to the freezerTable schema (hashes, headers, bodies...) and uses block number as the index, I'm seeing about 2 blocks/second upload, which will take about 2 months to upload for the classic chain's current height. Further, creating 50million relatively tiny objects may have negative implications for the S3 request costs, where I expect fewer, larger objects will be cheaper.

IMO this is beyond usable for most cases, so we need to find a way to make uploads more efficient.

My understanding so far is that most of our upload time is due to transaction overhead (even though we're batching uploads by up to 2048 blocks). The upside of block/kind-atomic resources is that we get to download on-demand just what we need, which, in my experience trying out the JS console eth.getBlock for remote blocks is "fast" as-is (barely noticeable difference from local FS).

Grouping resources by block (instead of by kind/block) saw about 8 blocks/second upload. I'm going to try reverting to this pattern, but then extending it further to use 32-block objects, with each containing all the tables. If this moves the upload time from 2 blocks/second to 2*4*32 = 256 blocks/second then I'm going to call that good enough. The downside is that download will take longer, and will download stuff that isn't necessary.

There is probably a further way of managing this by using an AWS Lambda to partition or group the objects once they're uploaded, but I'm going to call that out-of-scope for now.

As-is:

2020-06-08-211829_771x684_screenshot
2020-06-08-211855_764x994_screenshot

I guess what's behind the slow block upload speed, is it because it seeks on s3 prior to upload? Or is it simply not using a persistent connection to upload?

@meowsbits
Copy link
Member

meowsbits commented Jun 10, 2020

I guess what's behind the slow block upload speed, is it because it seeks on s3 prior to upload? Or is it simply not using a persistent connection to upload?

To be honest I'm not exactly sure. My googling and esoteric forum lurking lead me to "request transaction overhead"-type explanations. Batching (the new SDK API) helps a lot, I'm sure, and although we're typically (during sync) rolling 2048 blocks into a batch, I'm not sure that we're actually making the most of that optimization opportunity. As-is, we are maintaining a single Session, as well as uploader and downloader instances.

There may also be "transaction overhead" beyond the simple HTTP requests, ie something on the Amazon end with what it costs them (transaction-wise) to create objects -- and we're creating a significant number of rather small objects. They charge per-PUT, so I have to think that although it's in USD "cheap"(-ish), it may speak to the apparent slowness.

In general my intuition is that S3 for millions of tiny things is probably less ideal than S3 for hundreds of thousands of medium-sized things, etc.

With that said, still, I am not completely satisfied with it as an explanation for why 10M small objects take 2-3 weeks to upload to S3 (although one will find horror stories of long waits to delete large numbers of objects from buckets in the forums). Further investigation might want to create an isolated test case that's totally separate from this blockchain implementation and just try fiddling around with configurations and implementation to get a feel if it's our implementation or if it's just gonna be something like this no matter what.

@meowsbits
Copy link
Member

last 2 commits fix:

anic: runtime error: slice bounds out of range [11:10]

goroutine 384 [running]:
github.com/ethereum/go-ethereum/core/rawdb.(*freezerRemoteS3).TruncateAncients(0xc0001663c0, 0x1, 0x0, 0x0)
        /Users/zcstarr/src/etc_labs/core-geth/core/rawdb/freezer_remote_s3.go:337 +0xc0f
github.com/ethereum/go-ethereum/core/rawdb.(*freezerRemote).TruncateAncients(0xc0005b4000, 0x1, 0x0, 0x0)
        /Users/zcstarr/src/etc_labs/core-geth/core/rawdb/freezer_remote.go:171 +0x4a
github.com/ethereum/go-ethereum/core.(*BlockChain).truncateAncient(0xc02639e000, 0x0, 0x52d9c50, 0xc021120ee8)
        /Users/zcstarr/src/etc_labs/core-geth/core/blockchain.go:1016 +0x81
github.com/ethereum/go-ethereum/core.(*BlockChain).InsertReceiptChain.func2.1(0xc0211211f0, 0xc02639e000)
        /Users/zcstarr/src/etc_labs/core-geth/core/blockchain.go:1108 +0x60
github.com/ethereum/go-ethereum/core.(*BlockChain).InsertReceiptChain.func2(0xc0263bf850, 0x2, 0x2, 0xc08ea77a70, 0x2, 0x2, 0x0, 0x6f5c930, 0xc09574c380)
        /Users/zcstarr/src/etc_labs/core-geth/core/blockchain.go:1215 +0x1fa7
github.com/ethereum/go-ethereum/core.(*BlockChain).InsertReceiptChain(0xc02639e000, 0xc0263bf840, 0x2, 0x2, 0xc08ea77a40, 0x2, 0x2, 0x9fdae8, 0x0, 0x0, ...)
        /Users/zcstarr/src/etc_labs/core-geth/core/blockchain.go:1305 +0x1d0c
github.com/ethereum/go-ethereum/eth/downloader.(*Downloader).commitFastSyncData(0xc0248981c0, 0xc0263bf790, 0x2, 0x2, 0xc0002feb60, 0xc0263bf790, 0x2)
        /Users/zcstarr/src/etc_labs/core-geth/eth/downloader/downloader.go:1755 +0x68c
github.com/ethereum/go-ethereum/eth/downloader.(*Downloader).processFastSyncContent(0xc0248981c0, 0xc020a90240, 0x0, 0x0)
        /Users/zcstarr/src/etc_labs/core-geth/eth/downloader/downloader.go:1678 +0x351
github.com/ethereum/go-ethereum/eth/downloader.(*Downloader).syncWithPeer.func7(0xc00014b770, 0x0)
        /Users/zcstarr/src/etc_labs/core-geth/eth/downloader/downloader.go:529 +0x33
github.com/ethereum/go-ethereum/eth/downloader.(*Downloader).spawnSync.func1(0xc0248981c0, 0xc0211ce9c0, 0xc0212801a0)
        /Users/zcstarr/src/etc_labs/core-geth/eth/downloader/downloader.go:543 +0x63
created by github.com/ethereum/go-ethereum/eth/downloader.(*Downloader).spawnSync
        /Users/zcstarr/src/etc_labs/core-geth/eth/downloader/downloader.go:543 +0xaf

@meowsbits
Copy link
Member

meowsbits commented Jun 11, 2020

Worth noting that AWS S3 Region chosen will also matter a lot, as well as internet connection (for example, AWS seems to not like some of my VPN endpoints).

@meowsbits
Copy link
Member

meowsbits commented Jun 11, 2020

With latest push I'm getting around 150-200 blocks/second.

Latest push now uses 32-block groups for object storage. For example, object blocks/000000032.json contains blocks 32-63, encoded in an ordered JSON array.

And I turned my VPN off, so my internet is now on the same continent as my AWS bucket region.

image
image

And initialization from S3 freezer seems to work (nuke your local db between runs):

INFO [06-11|13:36:06.924] Starting Geth on Ethereum Classic...
INFO [06-11|13:36:06.924] Bumping default cache on mainnet         provided=1024 updated=4096
INFO [06-11|13:36:06.927] Maximum peer count                       ETH=50 LES=0 total=50
INFO [06-11|13:36:06.927] Smartcard socket not found, disabling    err="stat /run/pcscd/pcscd.comm: no such file or directory"
INFO [06-11|13:36:06.950] Starting peer-to-peer node               instance=CoreGeth/v1.11.6-unstable-984826f4-20200611/linux-amd64/go1.14.3
INFO [06-11|13:36:06.950] Allocated trie memory caches             clean=614.00MiB dirty=1024.00MiB
INFO [06-11|13:36:06.950] Allocated cache and file handles         database=/home/ia/SAMSUNG_T5/e/sandbox/remote-freezer-develop2/geth/chaindata cache=2.00GiB handles=524288
INFO [06-11|13:36:07.039] New remote freezer                       freezer=s3 namespace=coregeth-classic-parasail
INFO [06-11|13:36:07.039] New session                              remote=s3 region=0xc000206440
INFO [06-11|13:36:07.039] Creating bucket if not exists            remote=s3 name=coregeth-classic-parasail
INFO [06-11|13:36:07.416] Bucket created                           remote=s3 name=coregeth-classic-parasail result="{\n  Location: \"/coregeth-classic-parasail\"\n}" elapsed=377.046183ms
INFO [06-11|13:36:07.416] Retrieving ancients number               remote=s3
INFO [06-11|13:36:07.470] Finished retrieving ancients num         remote=s3 n=18579
INFO [06-11|13:36:07.470] Initializing cache                       remote=s3 n=18579
INFO [06-11|13:36:07.573] Finished initializing cache              remote=s3
INFO [06-11|13:36:07.829] Persisted trie from memory database      nodes=12356 size=1.78MiB time=23.038484ms gcnodes=0 gcsize=0.00B gctime=0s livenodes=1 livesize=0.00B
INFO [06-11|13:36:07.966] Persisted trie from memory database      nodes=12356 size=1.78MiB time=37.055909ms gcnodes=0 gcsize=0.00B gctime=0s livenodes=1 livesize=0.00B
INFO [06-11|13:36:07.966] Initialised chain configuration          config="NetworkID: 1, ChainID: 61 Engine: ethash EIP1014: 9573000 EIP1052: 9573000 EIP1108: 10500839 EIP1344: 10500839 EIP140: 8772000 EIP145: 9573000 EIP150: 2500000 EIP152: 10500839 EIP155: 3000000 EIP160$
 3000000 EIP161abc: 8772000 EIP161d: 8772000 EIP170: 8772000 EIP1884: 10500839 EIP198: 8772000 EIP2028: 10500839 EIP211: 8772000 EIP212: 8772000 EIP213: 8772000 EIP214: 8772000 EIP2200: 10500839 EIP658: 8772000 EIP7: 1150000 EthashECIP1010Continue: 5000000 EthashECIP1010Pa$
se: 3000000 EthashECIP1017: 5000000 EthashECIP1041: 5900000 EthashEIP100B: 8772000 EthashEIP2: 1150000 EthashHomestead: 1150000 "
INFO [06-11|13:36:07.966] Disk storage enabled for ethash caches   dir=/home/ia/SAMSUNG_T5/e/sandbox/remote-freezer-develop2/geth/ethash count=3
INFO [06-11|13:36:07.966] Disk storage enabled for ethash DAGs     dir=/home/ia/.ethash count=2
INFO [06-11|13:36:07.966] Initialising Ethereum protocol           versions="[65 64 63]" network=1 dbversion=<nil>
WARN [06-11|13:36:07.966] Upgrade blockchain database version      from=<nil> to=7
INFO [06-11|13:36:08.972] Initializing database from freezer       total=18579 number=416 hash="9132b6…f2b7ac" elapsed=1.005s
INFO [06-11|13:36:17.030] Initializing database from freezer       total=18579 number=3552 hash="1b25ec…f5502f" elapsed=9.063s
INFO [06-11|13:36:25.080] Initializing database from freezer       total=18579 number=6752 hash="60ce83…cf3161" elapsed=17.113s
INFO [06-11|13:36:33.104] Initializing database from freezer       total=18579 number=10144 hash="a6ae29…047958" elapsed=25.137s
INFO [06-11|13:36:41.139] Initializing database from freezer       total=18579 number=13536 hash="3500e9…94829e" elapsed=33.172s
INFO [06-11|13:36:49.180] Initializing database from freezer       total=18579 number=16960 hash="9a211b…a00a2e" elapsed=41.213s
INFO [06-11|13:36:52.666] Initialized database from freezer        blocks=18579 elapsed=44.699s
INFO [06-11|13:36:52.732] Loaded most recent local header          number=18578 hash="1baf58…84084c" td=9204680585820061 age=4y11mo5d
INFO [06-11|13:36:52.732] Loaded most recent local full block      number=0     hash="d4e567…cb8fa3" td=17179869184      age=51y2mo4d
INFO [06-11|13:36:52.732] Loaded most recent local fast block      number=18578 hash="1baf58…84084c" td=9204680585820061 age=4y11mo5d
INFO [06-11|13:36:52.732] Upgrading chain index                    type=bloombits percentage=0
INFO [06-11|13:36:52.732] Indexed transactions                     blocks=1     txs=0 tail=18578 elapsed="123.491µs"
INFO [06-11|13:36:52.732] Regenerated local transaction journal    transactions=0 accounts=0
INFO [06-11|13:36:53.095] Allocated fast sync bloom                size=1.60GiB
INFO [06-11|13:36:53.109] Initialized fast sync bloom              items=12356 errorrate=0.000 elapsed=13.712ms
INFO [06-11|13:36:53.193] New local node record                    seq=1 id=b88c999c5d67e33b ip=127.0.0.1 udp=30303 tcp=30303
INFO [06-11|13:36:53.193] Started P2P networking                   self=enode://90c69ac7118154b1993c0c382991b97466997cf1051df8cb657755eb648507d9f31929315c8d549c4cfaabdfa196c364ca01a0cd15b0293e6b1b027f5f6f2c74@127.0.0.1:30303
INFO [06-11|13:36:53.194] IPC endpoint opened                      url=/home/ia/.ethereum/geth.ipc
INFO [06-11|13:36:53.225] New local node record                    seq=2 id=b88c999c5d67e33b ip=24.207.216.46 udp=30303 tcp=30303
INFO [06-11|13:36:53.226] Mapped network port                      proto=tcp extport=30303 intport=30303 interface=NAT-PMP(192.168.0.1)
INFO [06-11|13:36:53.247] Mapped network port                      proto=udp extport=30303 intport=30303 interface=NAT-PMP(192.168.0.1)
INFO [06-11|13:37:01.211] Block synchronisation started

@meowsbits
Copy link
Member

This happens on restart quite often:

INFO [06-11|14:04:58.465] Loaded most recent local fast block      number=0     hash="d4e567…cb8fa3" td=17179869184        age=51y2mo4d
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x1c0 pc=0xbffec2]

goroutine 1 [running]:
github.com/ethereum/go-ethereum/core.(*HeaderChain).SetCurrentHeader(0xc007174510, 0x0)
        /home/ia/go/src/github.com/ethereum/go-ethereum/core/headerchain.go:492 +0xa2
github.com/ethereum/go-ethereum/core.(*BlockChain).Rollback(0xc00723a000, 0xc008b80000, 0x16371, 0x16b00)
        /home/ia/go/src/github.com/ethereum/go-ethereum/core/blockchain.go:982 +0x36a
github.com/ethereum/go-ethereum/core.NewBlockChain(0x18efe60, 0xc000eeeda0, 0xc005502800, 0x1900b80, 0x24876e0, 0x18ed540, 0xc0065e8620, 0x0, 0x0, 0x0, ...)
        /home/ia/go/src/github.com/ethereum/go-ethereum/core/blockchain.go:304 +0x11e0
github.com/ethereum/go-ethereum/eth.New(0xc000328c00, 0xc000471200, 0x1456d00, 0xc000397890, 0x423838)
        /home/ia/go/src/github.com/ethereum/go-ethereum/eth/backend.go:208 +0xa2c
github.com/ethereum/go-ethereum/cmd/utils.RegisterEthService.func2(0xc000328c00, 0xc0001eb650, 0xc000397a10, 0xc000387980, 0x2)
        /home/ia/go/src/github.com/ethereum/go-ethereum/cmd/utils/flags.go:1757 +0x3d
github.com/ethereum/go-ethereum/node.(*Node).Start(0xc0001fa000, 0x0, 0x0)
        /home/ia/go/src/github.com/ethereum/go-ethereum/node/node.go:210 +0x3f8
github.com/ethereum/go-ethereum/cmd/utils.StartNode(0xc0001fa000)
        /home/ia/go/src/github.com/ethereum/go-ethereum/cmd/utils/cmd.go:67 +0x2f
main.startNode(0xc000186160, 0xc0001fa000)
        /home/ia/go/src/github.com/ethereum/go-ethereum/cmd/geth/main.go:398 +0x7e
main.geth(0xc000186160, 0x0, 0x0)
        /home/ia/go/src/github.com/ethereum/go-ethereum/cmd/geth/main.go:386 +0x12a
gopkg.in/urfave/cli%2ev1.HandleAction(0x12a55c0, 0x15dc640, 0xc000186160, 0xc0003a0960, 0x0)
        /home/ia/go/pkg/mod/gopkg.in/urfave/cli.v1@v1.20.0/app.go:490 +0xc8
gopkg.in/urfave/cli%2ev1.(*App).Run(0xc0000be1a0, 0xc0000320c0, 0xc, 0xc, 0x0, 0x0)
        /home/ia/go/pkg/mod/gopkg.in/urfave/cli.v1@v1.20.0/app.go:264 +0x5dd
main.main()
        /home/ia/go/src/github.com/ethereum/go-ethereum/cmd/geth/main.go:282 +0x55

meowsbits added a commit that referenced this pull request Jun 11, 2020
#103 (comment)
Signed-off-by: meows <b5c6@protonmail.com>
@zcstarr
Copy link
Contributor Author

zcstarr commented Jun 26, 2020

Adding an a comment here. latest commit supports ancient remote as a json-rpc service

make all
AWS_REGION=us-west-1 AWS_PROFILE=developers-s3 build/bin/ancientremote  --rpcport 5000 --datadir.ancient.remote s3 --datadir.ancient.remote.namespace fubu --http.addr 127.0.0.1 --http

then

 env AWS_REGION=us-east-1 AWS_PROFILE=developers-s3 ./build/bin/geth   --classic   --ipcpath=~/.ethereum/geth.ipc   --datadir ~/.s3-core-z   --verbosity 4   --datadir.ancient.remote=client --datadir.ancient.remote.namespace zaner

The commands on both side need a little tlc, the client side should just take an rpcPort to connect to and a host, the
server side should do all the heavy lifting. I haven't cleaned up the edges yet, so everything is just hard coded to port 5000, and has some duplicate namespace specification.

@meowsbits let's sync soon and talk about restructuring the internals.

core/rawdb/schema.go Outdated Show resolved Hide resolved
eth/config.go Outdated Show resolved Hide resolved
zcstarr and others added 4 commits July 13, 2020 20:09
'freeze' function was implemented as a method of
freezer instances, where freezers should be objects
that satisfy the AncientStore interface defined in
ethdb/database.go

Implementing the experimental freezerRemote object
adjacent to freezer object demonstrated the brittle
way the actual freezing logic is implented, where
that logic is responsible for transitioning data from
the KV leveldb instance to the freezer.

This change allows the 'freeze' logic to be shared
between the (now) two freezer implementations.

Signed-off-by: meows <b5c6@protonmail.com>
Variable declarations default to the type's
zero value, so assigning to nil is ineffectual.

Signed-off-by: meows <b5c6@protonmail.com>
These log lines cause console tests testing
UI output to fail, ala
go test ./cmd/...

Commenting them will keep our CI useful,
while leaving breadcrumbs that are toggleable
and searchable.

Signed-off-by: meows <b5c6@protonmail.com>
This must have been erroneously added
somewhere along the line.

AFAIK it is completely unrelated to anything.

Signed-off-by: meows <b5c6@protonmail.com>
numFrozen replaces f.frozen (since the iterface doesn't provide
a field), replacing it with a function call to frdb.Ancients,
which provides the same value.

However, since we're not accessing the field directly, we need to
be careful about how we handle the logic around the assigned
value. The most implementation most equivalent to prior behavior
would be be call the method every time in lieu of f.frozen.
But this would be a lot of calls, and probably quite a bit slower.

The value of numFrozen will increment +1 every time AppendAncient
succeeds, so that logic is added. And rather than assigning the
value once prior to the for loop, the value is assigned with every
iteration of the loop via the method Ancients() call.

backoff logic is expected to handle method thrashing in the
same way that it wants to handle avoiding db thrashing.

Signed-off-by: meows <b5c6@protonmail.com>
…oint -> --ancient.rpc

- Remove IPC vs. HTTP/WS transport segregation, along with
node.Config.__IPC bool. We originally segregated IPC thinking
it would reduce ambiguity in configuration, but at this point
I think it causes an unworthy amount of finnicky and adhoc
logic through the configuration and constructor codes.

This change uses the exiting rpc.Client.Dial implementation
as the reference implementation, and simplifies the remote ancient
flags to one: --ancient.rpc. On the backend, then, this flag
value is simply passed to that rpc method. The node package
validates the URL with copy-pasted code from the RPC package
when necessary (for handling an empty-value default... which
arguably it shouldn't be doing at all anyways.)

Signed-off-by: meows <b5c6@protonmail.com>
Signed-off-by: meows <b5c6@protonmail.com>
Signed-off-by: meows <b5c6@protonmail.com>
Prevents false-negatives if test environment doesnt
have accessible networking, or if a preexiting colliding
geth service, eg. port 30303 in use.

Signed-off-by: meows <b5c6@protonmail.com>
fi will be nil if DNE

Signed-off-by: meows <b5c6@protonmail.com>
…endpoint

- Install configurable env var GETH_ANCIENT_RPC to
allow user to define an external endpoint handled by
an independent freezer server instance. This can be
a socket, http, ws, or stdio.

Note that since the AncientStore API doesn't have a reset-button,
running multiple tests against the same freezer instance
may have negative outcomes, since the data stores will not
represent consistent collection (chains).

If no external freezer is configured, the default
will create an ephemeral memory-packed freezer
server and connect to it over a temporary IPC socket.

Signed-off-by: meows <b5c6@protonmail.com>
This is a kind of manual reset for each test which
should allow a single remote freezer server instance
to handle multiple tests run serially.

The close method will be called likewise, so freezer
servers sensitive to that may be negatively effected.

Signed-off-by: meows <b5c6@protonmail.com>
@meowsbits
Copy link
Member

Just updated #103 (comment) with latest script, including latest changes to flag design, ie. --ancient.rpc.

76f8b65 adds a configurable GETH_ANCIENT_RPC env var which can be used to run blockchain tests against a remote freezer server, working as an integration test for both geth and the remote ancient store.

Here's my script for that, using the included memory-backed ancient store command ancient-store-mem (a lightweight, ephemeral-only, "mock" (not actually mock, but kind of) server):

#!/usr/bin/env bash

set -x

make all

echo "Starting ancient-store-mem (ephemeral remote ancient store)..."
(
./build/bin/ancient-store-mem ./ancient.ipc > ancient-store.log 2>&1
)&
aspid=$!
trap "kill -9 $aspid"

echo "Running tests..."
[ ! -S ./ancient.ipc ] && echo "Must have running freezer server with ipc at ancient.ipc" && exit 1
env GETH_ANCIENT_RPC="$(pwd)/ancient.ipc" go test -count=1 -v -run='_RemoteFreezer' ./core/... &> test.out
exited=$?

tail -40 test.out

echo "Finding unique method names called (to show completeness in method exercise)"
cat ancient-store.log | grep 'mock server called' | cut -d'=' -f2 | cut -d' ' -f1 | sort | uniq

[ $exited = 0 ] && echo "PASS" || echo "FAIL"

exit $exited

Signed-off-by: meows <b5c6@protonmail.com>
Signed-off-by: meows <b5c6@protonmail.com>
node/node.go Outdated Show resolved Hide resolved
Signed-off-by: meows <b5c6@protonmail.com>
Signed-off-by: meows <b5c6@protonmail.com>
If testing against a non-ephemeral ancient db,
a non-zeroed db would fatally contaminate tests.

Signed-off-by: meows <b5c6@protonmail.com>
New command uses pre-existing builting FS ancient
store wrapped in an RPC server.

It doesnt work yet.

And the export-refactoring touched a lot of comments
that it probably shouldn't have.

Probably revert me.

Signed-off-by: meows <b5c6@protonmail.com>
Signed-off-by: meows <b5c6@protonmail.com>
This logic was checking and mutating a freezer url in
a way that was a vestige of how the freezer path is handled
for the builtin freezer fs implementation.

Instead of using supervisory logic, we can just let the raw
value pass through to the rpc package where it will be
validated and used in context. Any errors coming from that
context will be raised.

This change also includes a tidbit of a wider parameter renaming
that I'm going to commit next.

Signed-off-by: meows <b5c6@protonmail.com>
This gives descriptiveness and consistency.

Signed-off-by: meows <b5c6@protonmail.com>
Signed-off-by: meows <b5c6@protonmail.com>
Signed-off-by: meows <b5c6@protonmail.com>
This was a sketch of a good idea, but is out of scope
for the current feature.

The deleted code established a remote freezer server
that would behave exactly like the built in filesystem
freezer, but do so via RPC communication, and thus
be able to replicate geth's ancient datadir store
remotely and possibly for multiple clients.

But not yet.

Signed-off-by: meows <b5c6@protonmail.com>
This reverts commit 1ab7cab.

This change made a big programmatic refactoring
which exported the rawdb.freezer struct and constructor.
This was intended to enable the hypothetical cmd/ancient-store-fs
command, which has since been abandoned for now.
Signed-off-by: meows <b5c6@protonmail.com>
Apparently it takes a lil longer for indices initialization
here. Or I just got unlucky.

Signed-off-by: meows <b5c6@protonmail.com>
@meowsbits
Copy link
Member

Closed via the merge of #168

@meowsbits meowsbits closed this Sep 8, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants