slipstream: take txs from anyone, get them into the pool's blocks - #83
Merged
Merged
Conversation
A new service, slipstream/, alongside payout/. It takes a raw tx over HTTP and hands it straight to the enforcer's block template server -- the one the proxy mines from -- which keeps it in its template mempool and never relays it (LayerTwo-Labs/bip300301_enforcer#642). That is how the pool mines BIP300/301 txs the network will not carry, or any other consensus-valid tx. The fee rule is Slipstream's: the higher of a floor (1 sat/vB) and the current mineable rate, read off the template being mined. A tx that pays less is taken back out of the enforcer before the refusal returns. Every submission is kept, refused ones included, and each accepted tx is followed from template to block: pending, in_template, mined, confirmed, or dropped/expired with a reason. The enforcer forgets a tx on restart or reorg; this side remembers, so it resubmits. It keeps its own slipstream.db and only reads shares.db, for pool_meta and blocks_found. info.json is served here: facts from pool_meta, with mode the exact pool_mode, presentation from env. tests/test_slipstream_regtest.sh runs it against a real enforcer built with --enable-slipstream. It is not in CI until an enforcer release ships the flag; the unit tests are.
Suggested by the enforcer's maintainer, and simpler by a wide margin: the enforcer's template mempool mirrors the pool's bitcoind over ZMQ, so a tx that node accepts reaches the templates the proxy mines with no enforcer change at all. The enforcer-side pool this replaces (cusf-enforcer-mempool#130, bip300301_enforcer#642) is closed. A tx is now checked with testmempoolaccept and broadcast with sendrawtransaction. Nothing can be taken back out of a mempool, so the fee rule runs between the two: a tx that pays too little is refused before it is ever sent. Non-standard txs need the node to run -acceptnonstdtxn, which Core allows only off mainnet; BIP300 deposits are standard on a patched node already. The trade: a tx is relayed like any other, so another pool may mine it. mined_by_pool says whose block it was. Tracking follows the node. A tx that leaves the mempool unmined is sent again, and the node's answer decides between pending and dropped (with its reason); an orphaned block's tx comes back to pending when the node restores it. There is no expiry and no withdrawal: Core has its own mempool expiry and no RPC to remove a tx. tests/test_slipstream_regtest.sh now runs against the stock release enforcer, so it runs in CI. scripts/regtest/start.sh is back as it was.
…ate-limit key - deploy/systemd/simplepool-slipstream.service and deploy/nginx/slipstream.conf, templates in the form install.sh already renders (@user@ / @root@), with the install steps in slipstream/README.md. install.sh does not set slipstream up yet. - docs/simplepool.html gains a Slipstream section (with its sequence diagram, generated like the others) and a Dashboard section listing every page and endpoint, plus slipstream.db in the data model. Also brought up to date where it had fallen behind: the proxy long-polls the enforcer, the payout worker runs in three modes, not one, and the footer still called this a solo and PPS pool. - The rate limit behind a proxy was keyed on the FIRST X-Forwarded-For hop, which the client writes itself, so any client could pick its own key. It is now the last hop, the one the proxy added, and the vhost template overwrites the header rather than appending to it.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
This adds a new service,
slipstream/, alongsidepayout/. Anyone can POST it a raw tx, and it gets that tx into the pool's blocks. That includes txs the network will not relay, such as BIP300/301 txs (deposits, withdrawal bundles, BMM requests), or any other consensus-valid tx.The tx goes to the pool's own bitcoind. The enforcer's template mempool mirrors that node over ZMQ, so once the node accepts a tx it reaches the templates the proxy mines. The enforcer is unchanged, and the enforcer's own BIP300 rules still apply on the way in.
The node
-acceptnonstdtxn=1.acceptnonstdtxn is not currently supported for main chain. This was checked against the drivechain-patched, ecash betanet and stock builds. The flag works on signet and regtest.main, so non-standard txs there need a patched Core that lifts the check.mined_by_poolrecords whose block it was.How it behaves
SLIPSTREAM_MIN_FEE_RATE) and the current mineable rate. This follows Slipstream's own rule.testmempoolacceptgives the fee and size without broadcasting, and only a tx that passes both the node and the rule reachessendrawtransaction.slipstream_submissionskeeps every POST exactly as it arrived, including refusals and their reasons.pending,in_template,mined(withmined_by_poolfromblocks_found) andconfirmed.pendinganddropped, and adroppedtx carries the node's reason.pendingwhen the node restores it.slipstream_events.GET /info.json.pool_meta:mode(the exactpool_mode),fee_bps,coinbase_tagand the addresses. They are never configured here.POOL_NAME,POOL_CHAIN(e.g.betanet),POOL_LOGO, the public URLs and so on.slipstream_urlis included.Storage
The service keeps its own
slipstream.db. It never writes toshares.db, and reads it only forpool_metaandblocks_found.Also in this PR
Dockerfile.slipstream, aslipstreamcompose service bound to loopback (publish it through nginx withSLIPSTREAM_TRUST_PROXY=1), and the image in the GHCR build matrix.node-tests, and the end-to-end test runs inintegration-test.deploy/systemd/simplepool-slipstream.serviceanddeploy/nginx/slipstream.conf, in the@USER@/@ROOT@forminstall.shalready renders. The install steps are inslipstream/README.md.install.shdoes not set slipstream up yet.slipstream/README.md, plus short entries in the README andtests/README.md.docs/simplepool.htmlgains a Slipstream section, with a generated sequence diagram (sequence-diagrams.py --checkpasses).docs/simplepool.htmlgains a Dashboard section listing every page and endpoint, andslipstream.dbjoins the data model.Fixed along the way
Behind nginx, the rate limit was keyed on the first
X-Forwarded-Forhop. The client writes that one itself, so any client could choose its own key. It is now keyed on the last hop, the one the proxy added, and the vhost template overwrites the header rather than appending to it. There is a unit test for it.Testing
cd slipstream && npm test: 25 unit tests against a fake bitcoind and enforcer.tests/test_slipstream_regtest.sh, against patched bitcoind (acceptnonstdtxn=1) and the stock release enforcer. Passed locally, and now runs in CI:in_template.generateblockmines that template. The history readsaccepted, in_template, mined, confirmed.fee-rate-too-lowand never reaches the node's mempool.bumpfeein the node's mempool is recorded asdropped, with the node's reason:insufficient fee, rejecting replacement ..../api/feesanswer.Not in this PR
/slipstreampage. That is dashboard: a Slipstream page #84, stacked on this PR.