bitcoin-faucet-shell icon indicating copy to clipboard operation
bitcoin-faucet-shell copied to clipboard

bublina faucet amounts are really small

Open ajtowns opened this issue 1 year ago • 8 comments

Hi,

https://signetfaucet.bublina.eu.org/ is sending really small amounts, eg 836 sats in https://mempool.space/signet/tx/9337037cad2c0f441e7802a356d9c794f962894cd89900dafb5228670d2acc48 despite having 6k sBTC in its wallet. Is there any reason for it to be so crazy low? The code here seems to imply a value between 5000 sats and 332670 sats, so presumably is not current anymore.

Doing something like:

 $ bitcoin-cli -signet getbalance > BALANCE.new; mv BALANCE.new BALANCE
 $ python3 -c 'import random; print("%.8f" % ((random.random()+1)/2e6*min(6000,float(open("BALANCE").read().strip()))))'

would let you have a random amount that scales with the faucet wallet's balance.

ajtowns avatar Sep 17 '24 03:09 ajtowns

Hi!

Thank you for the feed-back!

Yes, the faucet service was being recently used as a honeypot for gathering addresses since the limits are shared between multiple different faucets.

See for example this:

https://mempool.space/signet/tx/70f7322888a545a157c4cc46b594e7aa39a107ac44c4b2a0d5a13946a67a0680

This bot seems to not be bothered by the low amount. And the IP(v4 in this case) addresses of these Goodline (around the world) clients will be denied service by this and befriended faucets on the next try.

Thanks for the code suggestion! To see the faucet's current GET.sh script head over to https://signetfaucet.bublina.eu.org/cgi-bin/GET.sh.txt and notice that many lines are commented-out. The amount is not being determined by this script anymore, nor by the client-supplied optional API parameter.

I was thinking more about adding a "captcha-like" parameter where the requestor will need to supply the current block's height and shortened code (last doublet of the block hash and doublets' "check" in one byte, doing three unpredictable and easily verifiable bytes together). Example: Signet block 213581 aa3b a1 (where a1 in the end stands for 10 (hex A) doublets which do not contain zero and 1 all-zero doublet)

       _|_|      _|  _|_|_|    
     _|    _|  _|_|        _|  
         _|      _|    _|_|    
       _|        _|        _|  
     _|_|_|_|    _|  _|_|_|    

     _|_|_|_|    _|_|      _|  
     _|        _|    _|  _|_|  
     _|_|_|      _|_|      _|  
           _|  _|    _|    _|  
     _|_|_|      _|_|      _|  

  ,---   .123 4567 89ab cdef   ---,
  | ..   .... .127 8f59 a752   .f |
  | 1.   f17. 9335 a5be 731f   1f |
  | 2.   257. 8cc4 a541 e3.7   2f |
  | 3.   1dd2 d71. cdc2 aa3b   3f |
  '===   ==== ==== ==== ====   ==='
   sk:   aa3b a1

Maybe some young blood, an apprentice, could help so if you know anyone interested, please send them my way.

The amount was changed now (see example) to send two-fold more sats which may resemble real stacking. See signetfaucet.sh, mktas.sh and most importantly awklist.sh. fee.sh just returns the vsize of the decoded Bitcoin transaction (using bch.sh inside any network directory so one does not need to add -datadir or -chain to bitcoin-cli, see cls for more).

jsarenik avatar Sep 17 '24 07:09 jsarenik

@ajtowns and yes, the current faucet's balance is 6273.38730076, but was around 2500 few months ago. I am feeding it from fauCAT (one machine here running Signet in Inquisition).

jsarenik avatar Sep 17 '24 07:09 jsarenik

@ajtowns and yes, the current faucet's balance is 6273.38730076, but was around 2500 few months ago. I am feeding it from fauCAT (one machine here running Signet in Inquisition).

Seems a little bit wasteful; if you want more, just ask? Or I could do the same thing I'm doing for my and kalle's faucet and just automatically feed a percentage of the coinbase reward your way?

I was thinking more about adding a "captcha-like" parameter where the requestor will need to supply the current block's height and shortened code

I feel like spammer folks will just automate that, and it'll only end up inconveniencing the newbs that we'd like to help... Hmm, random idea; how hard would it be to do auth via github, and then rate limit by github account (0.01 sbtc first time, 0.25 sbtc/week thereafter)? Maybe something like that could work...

ajtowns avatar Sep 17 '24 08:09 ajtowns

FWIW, we tweaked up kalle's faucet code to (a) batch payments, (b) send the batches at regular intervals, (c) limit the maximum total funds sent in a batch; but that's all in python, and is probably annoying to translate to shell. Could be worth looking at; makes spam attacks a little self-limiting.

ajtowns avatar Sep 17 '24 08:09 ajtowns

Or I could do the same thing I'm doing for my and kalle's faucet and just automatically feed a percentage of the coinbase reward your way?

You should start getting 100 sBTC every 50 blocks shortly.

ajtowns avatar Sep 17 '24 08:09 ajtowns

Thanks for pointers! I have missed @kallewoof 's idea of batching that would silently ignore repeated requests from the same address. Let me think…

image

jsarenik avatar Sep 17 '24 08:09 jsarenik

First, let me say I thought about batching some time ago but without the addition of silently ignoring retries from the same IP, which I like a lot, but still do not know how to handle this

The "misuser" in this case has access to huge number of IPv4 addresses never seen before by this faucet (or at least addresses seen long time ago, enough that they were forgotten).

And this all even without publicly sharing what is my exact time of when the cleanup happens (an any other unsuccessful try would extend the time IP is remembered and blocked).

I am wondering if and how it would be possible to allow very easy operation without a "captcha" and still ignore the "bots".

Here are some ideas:

  • use Cloudflare Turnstile
  • use batching
    • batching would be done in mod 9 of a blockheight, so that there is time to silently remove any retries — example: batch=($height+(9-$height%9), the current Signet block is 214015 and batch=214020 and the batched entries are stored in $network-$batch directory in a simple form of a file named by IP address (easy to remove on retry) containing the receiving address to get sats from the faucet at)

jsarenik avatar Sep 20 '24 06:09 jsarenik

First, let me say I thought about batching some time ago but without the addition of silently ignoring retries from the same IP, which I like a lot, but still do not know how to handle this

At some point, it's probably better to just not worry about it? We can always do a signet reset of some sort and start redistributing coins from scratch if it becomes too big a deal; but as it stands the 20.1 sBTC that wallet has accumulated is less than a single block's reward currently, and given the current distribution, the bublina faucet will recover that amount within ~10 blocks.

  • batching would be done in mod 9 of a blockheight,

A delay of ~4 blocks (on average) is expected to be about 40 minutes, which seems like a long time to wait. Just remembering the last 9, 144, 1008, 2016 blocks worth of requests and trimming duplicates would probably be friendlier?

ajtowns avatar Sep 23 '24 09:09 ajtowns

Looks like someone's spamming the faucet and triggering lots of transactions and block space usage atm. https://github.com/ajtowns/faucet-waltz might be a useful approach if you want to look at implement batching.

ajtowns avatar Dec 16 '24 04:12 ajtowns

Thank you for the inspiration in faucet-waltz. Yes, much higher fees than needed are currently being paid by the alt signet faucet. It is intentional and as far as I can say there is no more spam than there already was. The faucet itself is currently quite unusable for humans. I know it and think about it. The inspiration is helpful for me.

jsarenik avatar Dec 16 '24 08:12 jsarenik

And as for triggering lots of transactions and block space I am actually happy someone other than me started to do such activity. I used to do such mempool-filling experiments at tb1q8z0jcrdmfuhyafz06ukhyvfnx4vhcn5azv6jkr (mempool.space) not so long time ago.

What I am thinking about is long into the future when most of the nodes will not have enough HDD/SSD space to accomodate all the past blocks and rather run a pruned node. The chainstate is the primary source anyway and the block chain is good only to keep chainstate current (and the old blocks can be safely discarded as there are still some full-historical nodes running). One can actually run a pruned node with 100GB of last blocks and seeding a pruned node is as simple as https://pn.bublina.eu.org/ (was alt.prunednode.today).

On a signet of one miner when we exactly know the inputs and outputs one can easily do "high-fee spam" to discourage other spammers :) The point is to learn Bitcoin anyway and everyone can run their own custom signet network anyway. No need to support spam with real resources (machines running mempool.space/signet). This idea came to me when I thought about "there is no signet" in https://github.com/bitcoin/bitcoin/pull/29838#issuecomment-2517350643 (like "there is no spoon").

jsarenik avatar Dec 16 '24 09:12 jsarenik

Yeah, I think the first page being all bublina txs confused me into thinking that more of the txs were bublina drops than there really were, so that batching would be a much more significant reduction. For only a dozen or two txs per block, not such a big deal, but still, batching up every 30s or 1m seems better practice than not.

ajtowns avatar Dec 16 '24 10:12 ajtowns

Yes. Working on it. Moving in that direction but also considering repetitive RBF of that big batched faucet payout. Huge amount of spam was eliminated already and my high faucet-tx fees seem to have raised the mempool-fillers' fees (and keep raising them further as my rule is dynamic and uses the mempool emphasis which is total_fee_sats / bytes).

Following is a mind-dump:

In the meantime I have sent some sats to 0x51 (all three variants i.e. p2sh, p2sh-segwit and wsh, the spends of whose can be for reference found at testnet4 equivalents).

Also SHA1 hash collision addresses have been filled with some sats:

$ bitcoin-cli -signet decodescript 6e879169a77ca787
{
  "asm": "OP_2DUP OP_EQUAL OP_NOT OP_VERIFY OP_SHA1 OP_SWAP OP_SHA1 OP_EQUAL",
  "desc": "raw(6e879169a77ca787)#fs0w90e0",
  "type": "nonstandard",
  "p2sh": "2MyJKxYR2zNZZsZ39SgkCXWCfQtXKhnWSWq",
  "segwit": {
    "asm": "0 f3d0f98efa8cc49043d22817cb07dec9d7cfea517f44b1ee2b161081dbf903b8",
    "desc": "addr(tb1q70g0nrh63nzfqs7j9qtukp77e8tul6j30aztrm3tzcggrkleqwuqdd5cne)#97hd7y7l",
    "hex": "0020f3d0f98efa8cc49043d22817cb07dec9d7cfea517f44b1ee2b161081dbf903b8",
    "address": "tb1q70g0nrh63nzfqs7j9qtukp77e8tul6j30aztrm3tzcggrkleqwuqdd5cne",
    "type": "witness_v0_scripthash",
    "p2sh-segwit": "2N3496o6hZYdfmoob53vjm9oFcv6XzjqsSr"
  }
}

The example spend can be found on mainnet and easily adjusted.

Commented transaction with newlines added for readability:

# version
01000000
# one input
01
f3733679c44cae3edfe7e36c017f036a43498049f9a6d247505e61802de58dbc 00000000 fd 028f 4d4001255044462d312e330a25e2e3cfd30a0a0a312030206f626a0a3c3c2f57696474682032203020522f4865696768742033203020522f547970652034203020522f537562747970652035203020522f46696c7465722036203020522f436f6c6f7253706163652037203020522f4c656e6774682038203020522f42697473506572436f6d706f6e656e7420383e3e0a73747265616d0affd8fffe00245348412d3120697320646561642121212121852fec092339759c39b1a1c63c4c97e1fffe017f46dc93a6b67e013b029aaa1db2560b45ca67d688c7f84b8c4c791fe02b3df614f86db1690901c56b45c1530afedfb76038e972722fe7ad728f0e4904e046c230570fe9d41398abe12ef5bc942be33542a4802d98b5d70f2a332ec37fac3514e74ddc0f2cc1a874cd0c78305a21566461309789606bd0bf3f98cda8044629a14d4001255044462d312e330a25e2e3cfd30a0a0a312030206f626a0a3c3c2f57696474682032203020522f4865696768742033203020522f547970652034203020522f537562747970652035203020522f46696c7465722036203020522f436f6c6f7253706163652037203020522f4c656e6774682038203020522f42697473506572436f6d706f6e656e7420383e3e0a73747265616d0affd8fffe00245348412d3120697320646561642121212121852fec092339759c39b1a1c63c4c97e1fffe017346dc9166b67e118f029ab621b2560ff9ca67cca8c7f85ba84c79030c2b3de218f86db3a90901d5df45c14f26fedfb3dc38e96ac22fe7bd728f0e45bce046d23c570feb141398bb552ef5a0a82be331fea48037b8b5d71f0e332edf93ac3500eb4ddc0decc1a864790c782c76215660dd309791d06bd0af3f98cda4bc4629b1086e879169a77ca787 ffffffff
# one output
01
ba1f000000000000 16 0014a96ee818cbe2433505882cd2d8461470ed460ffe
# no witness here, ends with locktime
00000000

Also I enabled the LN anchor on the faucet. And anyone can spend from there.

Any other ideas? I think about adding P2PK to the faucet (both 03/compressed and 04/uncompressed public keys).

jsarenik avatar Dec 17 '24 08:12 jsarenik

The lots of blockspace usage seems to be the fiamma bitvm bridge testnet launch.

ajtowns avatar Dec 17 '24 08:12 ajtowns

The lots of blockspace usage seems to be the fiamma bitvm bridge testnet launch.

Yes. https://github.com/jsarenik/bitcoin-faucet-shell/discussions/7#discussion-7700448

jsarenik avatar Dec 17 '24 11:12 jsarenik

This is done already:

  • GET.sh uses referrer - see older comment for context
  • alt.signetfaucet.com works again
  • Schmaltz (rhymes with Waltz) development is being done separated without breaking the current Alt Faucet - at the moment no difference
  • unlimited RBF replacements were tested just to see if replaced transactions can be used for the batched faucet payouts

This is planned:

  • use CloudFlare Turnstile (prefer the invisible one)
  • switch Schmaltz to asynchronous faucet-waltz-like every-minute cron(1) operated RBF-replacing payout

jsarenik avatar Dec 22 '24 10:12 jsarenik

Turnstile is in use already

Now I''ll think about simple RBF script that takes an in-mempool txid and makes an unsigned raw hex replacement ready to be signed and sent.

When done, a Waltz implementation in shell follows and as a final step increasing the amount sent by Alt Signet faucet while updating this repository with current scripts.

Thank you for patience and please continue with providing me feedback.

jsarenik avatar Dec 24 '24 19:12 jsarenik

Faucets are small and often not available. How did sbtc come from? Was it excavated or simulated?

lilin998 avatar Jan 13 '25 11:01 lilin998

@lilin998 Read at https://en.bitcoin.it/wiki/Signet

jsarenik avatar Jan 13 '25 12:01 jsarenik

Waltz, i.e. for me mainly the idea of batching, is not going to be implemented on Alt. Here's the reason: let's think about a school which has Linux machines freely available to its students. One real human student is sitting at the keyboard. The other (or just a script) is connected remotely.

The chance that the second student's attempt results with a successful DoS for the first one is almost 100% (the only possible race would be a new block coming before IP-address-reuse triggers the RBF transaction sending the funds back to the faucet instead of the original requestor).

Back to this issue in its original form: how about the amounts now, @ajtowns ?

jsarenik avatar Jan 26 '25 08:01 jsarenik

I don't know why batching would result in a dos -- the way my code works is if two requests come in in a 60s period, they share a single tx for the payouts, and otherwise they don't.

The main benefit of batching is if you have 100 requests in a short period, then the payout txs are reduced from 60kvb (600vb each times 100tx) to ~26kvb (since you only need one signature instead of 100, and only need one change address instead of 1 per tx). That's valuable both for reducing the spam on signet when there are a bunch of people hitting the faucets, but also to help keep the faucet working -- otherwise you can only have 20 payouts per utxo per block due to ancestor/descendant limits, and I think atm you tend to keep all your funds in a single utxo as well.

The script also has logic to cap the total payout per tx/period, so that if you normally payout 0.025 sbtc per request, but get 100 requests in a period, each payout gets reduced to 0.0005 sbtc to ensure the total per tx is limited to 0.05 sbtc, so that it only spends 0.5 sbtc per block on average. I think some way of letting people get more btc during idle periods while having a cap during busy periods is a good idea, rather than just letting the faucets accrue thousands of sbtc. OTOH, at least the discord faucet has much longer idle periods than the 60s payout frequency I'm using, so maybe it needs something cleverer... (You're getting 2 sbtc per block on average, I think, so could have a limit of 0.1 sbtc in total every 30 seconds instead of 0.05 every 60 seconds)

ajtowns avatar Jan 28 '25 23:01 ajtowns

Yes. The single UTXO is intentional. I like having the limits enforced on a low level.

I use sqlite wallet but in a somewhat special way:

  1. The wallet can be refreshed at any time and after last such refresh it takes 108K (kilobytes)
  2. The change address is the same as the main address being used
  3. On refresh, the wallet is created blank with private keys enabled and the private key is imported under multiple output descriptors (wpkh, tr, pkh, sh(wpkh), wsh(pkh) - all using one single WIF private key)

Yes, batching similar to what you describe is going to be implemented here eventually. Just the main feature will be RBF so instead of paying high fees on each new transaction, the RBF takes just extra current vsize sats (after prolonging the transaction by current requested outputs, changing the "change" going back to the faucet and signing it).

jsarenik avatar Jan 29 '25 14:01 jsarenik

And today I changed the setting in my Signet faucet Bitcoin node to use prune=550 and everything works. I would personally like more if the blocks were full when mempool is full. Testnets (including Testnet4) do not resemble main Bitcoin and Signet also does not in terms of quarter-and-less-full blocks. People (from what I hear) are rather learning and losing their sats on mainnet (which is not that expensive at the moment).

Big thanks to you, @ajtowns, since this Alt faucet was in a very bad state when you started this issue. Respect. All the best success in what you do!

Here's a song for you: https://www.youtube.com/watch?v=-6gL3ArPb4E

jsarenik avatar Jan 29 '25 15:01 jsarenik

More than batching now. Requests are totally async. I hope it's useful.

The limit is now v3 tx size. I have not tested this limit thoroughly yet. Let's see what a crowd can do.

Have a nice weekend!

jsarenik avatar Jan 31 '25 12:01 jsarenik

Now it is in following state:

  • amounts are much higher
  • fee increments on RBF are much lower

What do you think?

jsarenik avatar Feb 03 '25 15:02 jsarenik

I can have a complete demonstration in my spare time because the faucet amount is too small. I tried https://github.com/bitcoin/bitcoin/blob/master/contrib/signet/readme.mdminer has been searching for many resources in the wallet description, but I didn't find a complete one.

lilin998 avatar Feb 04 '25 14:02 lilin998

MINER="./contrib/signet/miner" GRIND="./build/src/bitcoin-util grind" $MINER calibrate --grind-cmd="$GRIND" nbits=1e00f403 for 25s average mining time

CLI="./build/src/bitcoin-cli -conf=mysignet.conf" ADDR=$($CLI -signet getnewaddress) NBITS=1e00f403 $MINER --cli="$CLI" generate --grind-cmd="$GRIND" --address="$ADDR" --nbits=$NBITS

PSBT signing failed

lilin998 avatar Feb 04 '25 14:02 lilin998

@lilin998 please start a new issue

jsarenik avatar Feb 04 '25 17:02 jsarenik

Since this issue is the trigger that made the current alt.signetfaucet (signet25) to happen as it is, let me explain some details.

This faucet now does not use TRUC anymore but rather prepares a chain of 25 in-mempool transactions and keeps to RBF merely the last leaf with current faucet payouts.

The advantage of this approach in comparison with V3 (TRUC) is a much higher transaction size limit so that many more requests can be handled in one big payout transaction. So many more that the one-request-per-IP-per-block limit was lifted and is enforced only when there are more than 2016 requests being served in one payout and is reset back to lifted state when the payout transaction gets mined.

This approach still gives the same guarantee TRUC was being used for previously, but now depending just upon the fact that most of the network including the miners honor the default limitancestorcount of 25. The guarantee is that none of the requesters can mess with the fees using CPFP and so make the faucet pay too much on the next replacement, possibly draining it this way and causing a denial of service. This is attested in every single payout by paying sats to an LN anchor address. These sats get spent but not while their parent (the faucet payout transaction) is in the mempool.

I have been dreaming of such a faucet since 2018 :-)

images.jpeg

Thanks to Gloria Zhao for helping me to realize TRUC was not needed here.

jsarenik avatar Mar 09 '25 08:03 jsarenik