summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBilly Tetrud <billy.tetrud@gmail.com>2021-08-01 21:40:47 -0700
committerbitcoindev <bitcoindev@gnusha.org>2021-08-02 04:41:08 +0000
commit111ddd44e9fd220ea86135b9c9d99e27bb2f6933 (patch)
tree46e8fe0021aa65783a4a84970e1a2f89230a8589
parent5ee604f555de4c8c698247ff2b3e3cadb05e6ff1 (diff)
downloadpi-bitcoindev-111ddd44e9fd220ea86135b9c9d99e27bb2f6933.tar.gz
pi-bitcoindev-111ddd44e9fd220ea86135b9c9d99e27bb2f6933.zip
Re: [bitcoin-dev] Exploring: limiting transaction output amount as a function of total input value
-rw-r--r--fe/2ab567561ce5f734c653fb7b824390d6fd6990498
1 files changed, 498 insertions, 0 deletions
diff --git a/fe/2ab567561ce5f734c653fb7b824390d6fd6990 b/fe/2ab567561ce5f734c653fb7b824390d6fd6990
new file mode 100644
index 000000000..3157c402e
--- /dev/null
+++ b/fe/2ab567561ce5f734c653fb7b824390d6fd6990
@@ -0,0 +1,498 @@
+Return-Path: <fresheneesz@gmail.com>
+Received: from smtp3.osuosl.org (smtp3.osuosl.org [140.211.166.136])
+ by lists.linuxfoundation.org (Postfix) with ESMTP id F225BC000E
+ for <bitcoin-dev@lists.linuxfoundation.org>;
+ Mon, 2 Aug 2021 04:41:08 +0000 (UTC)
+Received: from localhost (localhost [127.0.0.1])
+ by smtp3.osuosl.org (Postfix) with ESMTP id DAF5860677
+ for <bitcoin-dev@lists.linuxfoundation.org>;
+ Mon, 2 Aug 2021 04:41:08 +0000 (UTC)
+X-Virus-Scanned: amavisd-new at osuosl.org
+X-Spam-Flag: NO
+X-Spam-Score: -2.098
+X-Spam-Level:
+X-Spam-Status: No, score=-2.098 tagged_above=-999 required=5
+ tests=[BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1,
+ DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FROM=0.001,
+ HTML_MESSAGE=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001,
+ SPF_PASS=-0.001] autolearn=ham autolearn_force=no
+Authentication-Results: smtp3.osuosl.org (amavisd-new);
+ dkim=pass (2048-bit key) header.d=gmail.com
+Received: from smtp3.osuosl.org ([127.0.0.1])
+ by localhost (smtp3.osuosl.org [127.0.0.1]) (amavisd-new, port 10024)
+ with ESMTP id fBXfO04b_wEB
+ for <bitcoin-dev@lists.linuxfoundation.org>;
+ Mon, 2 Aug 2021 04:41:06 +0000 (UTC)
+X-Greylist: whitelisted by SQLgrey-1.8.0
+Received: from mail-ed1-x531.google.com (mail-ed1-x531.google.com
+ [IPv6:2a00:1450:4864:20::531])
+ by smtp3.osuosl.org (Postfix) with ESMTPS id 79FF960652
+ for <bitcoin-dev@lists.linuxfoundation.org>;
+ Mon, 2 Aug 2021 04:41:06 +0000 (UTC)
+Received: by mail-ed1-x531.google.com with SMTP id v20so8677653eda.1
+ for <bitcoin-dev@lists.linuxfoundation.org>;
+ Sun, 01 Aug 2021 21:41:06 -0700 (PDT)
+DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025;
+ h=mime-version:references:in-reply-to:from:date:message-id:subject:to;
+ bh=Btrg3QyzSX/pjPBDg6tiMejGld/2pMlLMeY16SyZsP4=;
+ b=VF1eN2detN3N7CR+shOb7s+EU0O/jgRCbaXPRBUSiHqAEoGSRaWUFo3PaMmnabJG9S
+ Lv3sd2so60GYPPIB7UUwCYyKhVjz6eYgM9bIpZeYsV2sgB8fATtytvP/gPjnLKP0hsW+
+ mJdR0MJ8fRdghyy61qj+94L4RbDBsd6HKxMtpvKDudRGfawLmyc3IcZ9sTF/OT348ZF4
+ OS/T+yfjcdwECdpkVgVwqyYsmw2IuOTjt8qvVMeJqqcVkXveIGC9+UX6R529oE+lBcoW
+ nMKljBjnbbO6OfF5RWwQIJurw8cgOXdgaDhRG+Yr35ze2yOIWj8VRyrjda4M9tE0ypSR
+ o/2g==
+X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
+ d=1e100.net; s=20161025;
+ h=x-gm-message-state:mime-version:references:in-reply-to:from:date
+ :message-id:subject:to;
+ bh=Btrg3QyzSX/pjPBDg6tiMejGld/2pMlLMeY16SyZsP4=;
+ b=ttTUZe5bVBrzIh2U6GF3eJTeGZGcbcBubr+UkA9EHV1io56lCKGsTBKUFF1aGxmLh7
+ uA7cWZn9aR7tv4c+H4nDL4ehw2akypc5QL3yggS9da8dx6H5hCF0WHL8/aS2FQzD75Zm
+ RqVSfdhBjAg2Efh6JNVfdxBoKnAu1481D5W6tKS+J970VeGdodsQkBJEiX53MV9fBpQz
+ +LeZVf6LPKAOyILNC6oGCXJvRm/p7ebe9nVngzGpxeF5uBP9MxrJpem0mnZ/UdYLYk8K
+ AldwqsoMpr0RGbQr2Ng2z7L2/myB5ElBqUiZEZIbAY8evpFLljcok76WsAT8d0H+S8eW
+ eftA==
+X-Gm-Message-State: AOAM532Pepxiw1MwMdGu/dQ8FUeZKDhHBMpE0QtqfgUPu+tOs6FMErVc
+ O1u9Ho9Gi8EEGwg1N5+WXsWNc2hYlbIDZUXwnnQ=
+X-Google-Smtp-Source: ABdhPJzqo6ZDh9K0KDbihL5S2J6wJlj+kqIt0AuHEGw08B31A1bXoWfBQSyzGKRD8VTgl9634sPYnmc4g0x4sBV9UfM=
+X-Received: by 2002:a50:fb05:: with SMTP id d5mr16514737edq.5.1627879264540;
+ Sun, 01 Aug 2021 21:41:04 -0700 (PDT)
+MIME-Version: 1.0
+References: <CAGpPWDZ0aos5qHw2=popCpjuH7OXC0geEj8i3dwDTfP0j=or4w@mail.gmail.com>
+ <20210725053803.fnmd6etv3f7x3u3p@ganymede>
+ <CAGpPWDZ8EWd7kGV5pFZadQM1kqETrTK2zybsGF1hW9fx2oZb7w@mail.gmail.com>
+ <CAH+Axy7cPufMUCMQbCz2MUgRqQbgenAozPBFD8kPYrSjwcRG8w@mail.gmail.com>
+ <CAGpPWDb8yzGO-VtCO-x09e-phKHT7ezOms+DzeWc9vS3rN1AAw@mail.gmail.com>
+ <CAJ4-pEDWuNfdE4NXkZBsOnuSQ4YOv28YVwGavyiU+FPvpC6y1w@mail.gmail.com>
+ <CAGpPWDZL6BpzoNa0Qgf-Ux60fyWPjZH=NESkgbhEQO_My=XiAg@mail.gmail.com>
+ <CAJ4-pEBwdUJ3kg=yb-kWZLoaX5f_2t353K7Tr+dJy+JpAoKTmQ@mail.gmail.com>
+ <CAGpPWDYMZ+w3VSaLhR68f4WVq7NCUp3SedwW2e8QnRHOgLQqQg@mail.gmail.com>
+ <CAJ4-pEAT8Rrf7dN9A+F2SUvaRz0-DqgDw45whtZcWCTPeQ+uxA@mail.gmail.com>
+In-Reply-To: <CAJ4-pEAT8Rrf7dN9A+F2SUvaRz0-DqgDw45whtZcWCTPeQ+uxA@mail.gmail.com>
+From: Billy Tetrud <billy.tetrud@gmail.com>
+Date: Sun, 1 Aug 2021 21:40:47 -0700
+Message-ID: <CAGpPWDZ8sCEjqbN-PM4kc7k7K-3qUqzmHW8hHrBzh7tTJRUs6A@mail.gmail.com>
+To: Zac Greenwood <zachgrw@gmail.com>,
+ Bitcoin Protocol Discussion <bitcoin-dev@lists.linuxfoundation.org>
+Content-Type: multipart/alternative; boundary="0000000000004cdb6c05c88c2dc3"
+X-Mailman-Approved-At: Mon, 02 Aug 2021 08:02:49 +0000
+Subject: Re: [bitcoin-dev] Exploring: limiting transaction output amount as
+ a function of total input value
+X-BeenThere: bitcoin-dev@lists.linuxfoundation.org
+X-Mailman-Version: 2.1.15
+Precedence: list
+List-Id: Bitcoin Protocol Discussion <bitcoin-dev.lists.linuxfoundation.org>
+List-Unsubscribe: <https://lists.linuxfoundation.org/mailman/options/bitcoin-dev>,
+ <mailto:bitcoin-dev-request@lists.linuxfoundation.org?subject=unsubscribe>
+List-Archive: <http://lists.linuxfoundation.org/pipermail/bitcoin-dev/>
+List-Post: <mailto:bitcoin-dev@lists.linuxfoundation.org>
+List-Help: <mailto:bitcoin-dev-request@lists.linuxfoundation.org?subject=help>
+List-Subscribe: <https://lists.linuxfoundation.org/mailman/listinfo/bitcoin-dev>,
+ <mailto:bitcoin-dev-request@lists.linuxfoundation.org?subject=subscribe>
+X-List-Received-Date: Mon, 02 Aug 2021 04:41:09 -0000
+
+--0000000000004cdb6c05c88c2dc3
+Content-Type: text/plain; charset="UTF-8"
+
+Hey Zac,
+
+I think this could be a useful opcode. It kinda seems like UC1 and UC2 are
+basically the same use case: using rate-limiting to reduce risk of theft or
+mistake. I think this could be a helpful addition to a good wallet setup.
+
+I don't quite understand why you'd want to define a specific span of blocks
+for the rate limit. Why not just specify the size of the window (in blocks)
+to rate limit within, and the limit?
+
+You mentioned change addresses, however, with the parameters you defined,
+there would be no way to connect together the change address with the
+original address, meaning they would have completely separate rate limits,
+which wouldn't work since the change output would ignore the previous rate
+limit. I can think of the following options:
+
+A. You could always send change back to the *same* address. This is the
+simplest option, and the only downside I can think of is exposing the
+public key of an address. I'm not quite sure what the consensus is on the
+dangers of exposing the public key. It theoretically reduces quantum
+resistance a bit, but I think I read that some of taproot's mechanisms
+expose the bare public key, so maybe consensus has changed about that in
+recent years?
+
+B. Have some way to specify connected addresses in the output. This has the
+edge case that one of the addresses wouldn't be able to specify all the
+addresses that it should be connected with, because it would create a hash
+loop (ie if you had address A and B that should be connected, you can
+create address A and then specify that address B be connected to address A,
+but address A cannot specify its connection to B because A was created
+before B was created). You wouldn't want one address to be able to simply
+define a connection to another address, because this would open up attack
+vectors where people could encumber other people's addresses with rate
+limits connected to theirs. You could define connections based on
+signatures, which could be done without creating a hash loop, however it
+would require exposing the public keys of other addresses when you do that,
+at which point you might as well go with option A.
+
+C. You could specify that rate limits follow a certain output. Eg, if you
+create a transaction with destination output 1 and change output 2, your
+rate limiting opcode could specify that output 2 should inherit the rate
+limit. These inherited rate limits could all be connected together
+automatically.
+
+Another consideration is what to use for a receive-address. I would say the
+simplest option here is to receive at an address that contains an existing
+output already. If you allowed receiving at an address that contains no
+coins, you'd have to specify at least one other address to connect it with.
+This could work, but I don't see any advantage to it, since you don't gain
+any privacy by creating a new address if you're going to immediately
+programmatically tie it to the other addresses.
+
+One thing to consider is the cost of carrying around and checking these
+rate limits. Ideally it should be a very small amount of data carried
+around in the UTXO set, and be very cheap to verify when the opcode comes
+up. I think it would make sense for such an opcode to only be able to track
+rate-limits over short spans, like a month or less. Allowing the user to
+specify an arbitrary window over which to track a rate-limit seems like
+something that would probably open up a dos vector or other node resource
+usage abuse attacks. It might be useful enough to simply rate limit over
+each epoch (two weeks), but having a small set of options could also be
+useful (eg 1 day, 1 week, or 1 month).
+
+In any case, I'd be interested in seeing you write a BIP for this. Of
+course, don't take my word as community interest. I'm reasonably new to the
+bitcoin dev community, so definitely don't jump the gun based on my
+interest.
+
+On Sat, Jul 31, 2021 at 2:51 PM Zac Greenwood via bitcoin-dev <
+bitcoin-dev@lists.linuxfoundation.org> wrote:
+
+> Hi list,
+>
+> I'd like to explore whether it is feasible to implement new scripting
+> capabilities in Bitcoin that enable limiting the output amount of a
+> transaction based on the total value of its inputs. In other words, to
+> implement the ability to limit the maximum amount that can be sent from an
+> address.
+>
+> Two use cases come to mind:
+>
+> UC1: enable a user to add additional protection their funds by
+> rate-limiting the amount they are able to send during a certain period
+> (measured in blocks). A typical use case might be a user that intends to
+> hodl their bitcoin, but still wishes to occasionally send small amounts.
+> This avoids an attacker from sweeping all their funds in a single
+> transaction, allowing the user to become aware of the theft and intervene
+> to prevent further theft.
+>
+> UC2: exchanges may wish to rate-limit addresses containing large amounts
+> of bitcoin, adding warm- or hot-wallet functionality to a cold-storage
+> address. This would enable an exchange to drastically reduce the number of
+> times a cold wallet must be accessed with private keys that enable access
+> to the full amount.
+>
+> In a typical setup, I'd envision using multisig such that the user has two
+> sets of private keys to their encumbered address (with a "set" of keys
+> meaning "one or more" keys). One set of private keys allows only for
+> sending with rate-limiting restrictions in place, and a s second set of
+> private keys allowing for sending any amount without rate-limiting,
+> effectively overriding such restriction.
+>
+> The parameters that define in what way an output is rate-limited might be
+> defined as follows:
+>
+> Param 1: a block height "h0" indicating the first block height of an epoch;
+> Param 2: a block height "h1" indicating the last block height of an epoch;
+> Param 3: an amount "a" in satoshi indicating the maximum amount that is
+> allowed to be sent in any epoch;
+> Param 4: an amount "a_remaining" (in satoshi) indicating the maximum
+> amount that is allowed to be sent within the current epoch.
+>
+> For example, consider an input containing 100m sats (1 BTC) which has been
+> rate-limited with parameters (h0, h1, a, a_remaning) of (800000, 800143,
+> 500k, 500k). These parameters define that the address is rate-limited to
+> sending a maximum of 500k sats in the current epoch that starts at block
+> height 800000 and ends at height 800143 (or about one day ignoring block
+> time variance) and that the full amount of 500k is still sendable. These
+> rate-limiting parameters ensure that it takes at minimum 100m / 500k = 200
+> transactions and 200 x 144 blocks or about 200 days to spend the full 100m
+> sats. As noted earlier, in a typical setup a user should retain the option
+> to transact the entire amount using a second (set of) private key(s).
+>
+> For rate-limiting to work, any change output created by a transaction from
+> a rate-limited address must itself be rate-limited as well. For instance,
+> expanding on the above example, assume that the user spends 200k sats from
+> a rate-limited address a1 containing 100m sats:
+>
+> Start situation:
+> At block height 800000: rate-limited address a1 is created;
+> Value of a1: 100.0m sats;
+> Rate limiting params of a1: h0=800000, h1=800143, a=500k, a_remaining=500k;
+>
+> Transaction t1:
+> Included at block height 800100;
+> Spend: 200k + fee;
+> Rate limiting params: h0=800000, h1=800143, a=500k, a_remaining=300k.
+>
+> Result:
+> Value at destination address: 200k sats;
+> Rate limiting params at destination address: none;
+> Value at change address a2: 99.8m sats;
+> Rate limiting params at change address a2: h0=800000, h1=800143, a=500k,
+> a_remaining=300k.
+>
+> In order to properly enforce rate limiting, the change address must be
+> rate-limited such that the original rate limit of 500k sats per 144 blocks
+> cannot be exceeded. In this example, the change address a2 were given the
+> same rate limiting parameters as the transaction that served as its input.
+> As a result, from block 800100 up until and including block 800143, a
+> maximum amount of 300k sats is allowed to be spent from the change address.
+>
+> Example continued:
+> a2: 99.8 sats at height 800100;
+> Rate-limit params: h0=800000, h1=800143, a=500k, a_remaining=300k;
+>
+> Transaction t2:
+> Included at block height 800200
+> Spend: 400k + fees.
+> Rate-limiting params: h0=800144, h1=800287, a=500k, a_remaining=100k.
+>
+> Result:
+> Value at destination address: 400k sats;
+> Rate limiting params at destination address: none;
+> Value at change address a3: 99.4m sats;
+> Rate limiting params at change address a3: h0=800144, h1=800287, a=500k,
+> a_remaining=100k.
+>
+> Transaction t2 is allowed because it falls within the next epoch (running
+> from 800144 to 800287) so a spend of 400k does not violate the constraint
+> of 500k per epoch.
+>
+> As could be seen, the rate limiting parameters are part of the transaction
+> and chosen by the user (or their wallet). This means that the parameters
+> must be validated to ensure that they do not violate the intended
+> constraints.
+>
+> For instance, this transaction should not be allowed:
+> a2: 99.8 sats at height 800100;
+> Rate-limit params of a2: h0=800000, h1=800143, a=500k, a_remaining=300k;
+>
+> Transaction t2a:
+> Included at block height 800200;
+> Spend: 400k + fees;
+> Rate-limit params: h0=800124, h1=800267, a=500k, a_remaining=100k.
+>
+> This transaction t2a attempts to shift the epoch forward by 20 blocks such
+> that it starts at 800124 instead of 800144. Shifting the epoch forward like
+> this must not be allowed because it enables spending more that the rate
+> limit allows, which is 500k in any epoch of 144 blocks. It would enable
+> overspending:
+>
+> t1: spend 200k at 800100 (epoch 1: total: 200k);
+> t2a: spend 400k at 800200 (epoch 2: total: 400k);
+> t3a: spend 100k at 800201 (epoch 2: total: 500k);
+> t4a: spend 500k at 800268 (epoch 2: total: 1000k, overspending for epoch
+> 2).
+>
+> Specifying the rate-limiting parameters explicitly at every transaction
+> allows the user to tighten the spending limit by setting tighter limits or
+> for instance by setting a_remainder to 0 if they wish to enforce not
+> spending more during an epoch.
+>
+> I will stop here because I would like to gauge interest in this idea first
+> before continuing work on other aspects. Two main pieces of work jump to
+> mind:
+>
+> Define all validations;
+> Describe aggregate behaviour of multiple (rate-limited) inputs, proof that
+> two rate-limited addresses cannot spend more than the sum of their
+> individual limits.
+>
+> Zac
+>
+>
+>
+>
+>
+>
+> _______________________________________________
+> bitcoin-dev mailing list
+> bitcoin-dev@lists.linuxfoundation.org
+> https://lists.linuxfoundation.org/mailman/listinfo/bitcoin-dev
+>
+
+--0000000000004cdb6c05c88c2dc3
+Content-Type: text/html; charset="UTF-8"
+Content-Transfer-Encoding: quoted-printable
+
+<div dir=3D"ltr"><div>Hey Zac,</div><div><br></div><div>I think this could =
+be a useful opcode. It kinda seems like UC1 and UC2 are basically=C2=A0the =
+same use case: using rate-limiting to reduce risk of theft or mistake. I th=
+ink this could be a helpful addition to a good wallet setup.=C2=A0</div><di=
+v><br></div>I don&#39;t quite understand why you&#39;d want to define a spe=
+cific span of blocks for the rate limit. Why not just specify the size of t=
+he window (in blocks) to rate limit within, and the limit?=C2=A0<div><br></=
+div><div>You mentioned change addresses, however, with the parameters you d=
+efined, there would be no way to connect together the change address with t=
+he original address, meaning they would have completely separate rate limit=
+s, which wouldn&#39;t work since the change output would ignore the previou=
+s rate limit. I can think of the following options:=C2=A0</div><div><br></d=
+iv><div>A. You could always send change back to the *same* address. This is=
+ the simplest option, and the only downside I can think of is exposing the =
+public key of an address. I&#39;m not quite sure what the consensus is on t=
+he dangers of exposing the public key. It theoretically reduces quantum res=
+istance a bit, but I think I read that some of taproot&#39;s mechanisms exp=
+ose the bare public key, so maybe consensus has changed about that in recen=
+t years?</div><div><br></div><div>B. Have some way to specify connected add=
+resses in the output. This has the edge case that one of the addresses woul=
+dn&#39;t be able to specify all the addresses that it should be connected w=
+ith, because it would create a hash loop (ie if you had address A and B tha=
+t should be connected, you can create address A and then specify that addre=
+ss B be connected to address A, but address A cannot specify its connection=
+ to B because A was created before B was created). You wouldn&#39;t want on=
+e address to be able to simply define a connection to another address, beca=
+use this would open up attack vectors where people could encumber other peo=
+ple&#39;s addresses with rate limits connected to theirs. You could define =
+connections based on signatures, which could be done without creating a has=
+h loop, however it would require exposing the public keys of other addresse=
+s when you do that, at which point you might as well go with option A.=C2=
+=A0</div><div><br></div><div>C. You could specify that rate limits follow a=
+ certain output. Eg, if you create a transaction with destination output 1 =
+and change output 2, your rate limiting opcode could specify that output 2 =
+should inherit the rate limit. These inherited rate limits could all be con=
+nected together automatically.=C2=A0</div><div><br></div><div>Another consi=
+deration is what to use for a receive-address. I would say the simplest opt=
+ion here is to receive at an address that contains an existing output alrea=
+dy. If you allowed receiving at an address that contains no coins, you&#39;=
+d have to specify at least one other address to connect it with. This could=
+ work, but I don&#39;t see any advantage to it, since you don&#39;t gain an=
+y privacy by creating a new address if you&#39;re going to immediately prog=
+rammatically tie it to the other addresses.</div><div><br></div><div>One th=
+ing to consider is the cost of carrying around and checking these rate limi=
+ts. Ideally it should be a very small amount of data carried around in the =
+UTXO set, and be very cheap to verify when the opcode comes up. I think it =
+would make sense for such an opcode to only be able to track rate-limits ov=
+er short spans, like a month or less. Allowing the user to specify an arbit=
+rary window over which to track a rate-limit seems like something that woul=
+d probably open up a dos vector or other node resource usage abuse attacks.=
+ It might be useful enough to simply rate limit over each epoch (two weeks)=
+, but having a small set of options could also be useful (eg 1 day, 1 week,=
+ or 1 month).=C2=A0</div><div><br></div><div>In any case, I&#39;d be intere=
+sted in seeing you write a BIP for this. Of course, don&#39;t take my word =
+as community interest. I&#39;m reasonably new to the bitcoin dev community,=
+ so definitely don&#39;t jump the gun based on my interest.=C2=A0</div></di=
+v><br><div class=3D"gmail_quote"><div dir=3D"ltr" class=3D"gmail_attr">On S=
+at, Jul 31, 2021 at 2:51 PM Zac Greenwood via bitcoin-dev &lt;<a href=3D"ma=
+ilto:bitcoin-dev@lists.linuxfoundation.org" target=3D"_blank">bitcoin-dev@l=
+ists.linuxfoundation.org</a>&gt; wrote:<br></div><blockquote class=3D"gmail=
+_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204=
+,204);padding-left:1ex"><div dir=3D"ltr"><div>Hi list,</div><div><br></div>=
+<div>I&#39;d like to explore whether it is feasible to implement new script=
+ing capabilities in Bitcoin that enable limiting the output amount of a tra=
+nsaction based on the total value of its inputs. In other words, to impleme=
+nt the ability to limit the maximum amount that can be sent from an address=
+.</div><div><br></div><div>Two use cases come to mind:</div><div><br></div>=
+<div>UC1: enable a user to add additional protection their funds by rate-li=
+miting the amount they are able to send during a certain period (measured i=
+n blocks). A typical use case might be a user that intends to hodl their bi=
+tcoin, but still wishes to occasionally send small amounts. This avoids an =
+attacker from sweeping all their funds in a single transaction, allowing th=
+e user to become aware of the theft and intervene to prevent further theft.=
+</div><div><br></div><div>UC2: exchanges may wish to rate-limit addresses c=
+ontaining large amounts of bitcoin, adding warm- or hot-wallet functionalit=
+y to a cold-storage address. This would enable an exchange to drastically r=
+educe the number of times a cold wallet must be accessed with private keys =
+that enable access to the full amount.</div><div><br></div><div>In a typica=
+l setup, I&#39;d envision using multisig such that the user has two sets of=
+ private keys to their encumbered address (with a &quot;set&quot; of keys m=
+eaning &quot;one or more&quot; keys). One set of private keys allows only f=
+or sending with rate-limiting restrictions in place, and a s second set of =
+private keys allowing for sending any amount without rate-limiting, effecti=
+vely overriding such restriction.</div><div><br></div><div>The parameters t=
+hat define in what way an output is rate-limited might be defined as follow=
+s:</div><div><br></div><div>Param 1: a block height &quot;h0&quot; indicati=
+ng the first block height of an epoch;</div><div><div>Param 2: a block heig=
+ht &quot;h1&quot; indicating the last block height of an epoch;</div><div>P=
+aram 3: an amount &quot;a&quot; in satoshi indicating the maximum amount th=
+at is allowed to be sent in any epoch;<br></div><div>Param 4: an amount &qu=
+ot;a_remaining&quot; (in satoshi) indicating the maximum amount that is all=
+owed to be sent within the current epoch.</div></div><div><br></div><div>Fo=
+r example, consider an input containing 100m sats (1 BTC) which has been ra=
+te-limited with parameters (h0, h1, a, a_remaning) of (800000, 800143, 500k=
+, 500k). These parameters define that the address is rate-limited to sendin=
+g a maximum of 500k sats in the current epoch that starts at block height 8=
+00000 and ends at height 800143 (or about one day ignoring block time varia=
+nce) and that the full amount of 500k is still sendable. These rate-limitin=
+g parameters ensure that it takes at minimum 100m / 500k =3D 200 transactio=
+ns and 200 x 144 blocks or about 200 days to spend the full 100m sats. As n=
+oted earlier, in a typical setup a user should retain the option to transac=
+t the entire amount using a second (set of) private key(s).</div><div><br><=
+/div><div>For rate-limiting to work, any change output created by a transac=
+tion from a rate-limited address must itself be rate-limited as well. For i=
+nstance, expanding on the above example, assume that the user spends 200k s=
+ats from a rate-limited address a1 containing 100m sats:</div><div><br></di=
+v><div>Start situation:</div><div>At block height 800000: rate-limited addr=
+ess a1 is created;</div><div>Value of a1: 100.0m sats;</div><div>Rate limit=
+ing params of a1: h0=3D800000, h1=3D800143, a=3D500k, a_remaining=3D500k;</=
+div><div><br></div><div>Transaction t1:</div><div>Included at block height =
+800100;</div><div>Spend: 200k + fee;</div><div>Rate limiting params: h0=3D8=
+00000, h1=3D800143, a=3D500k, a_remaining=3D300k.</div><div><br></div><div>=
+Result:</div><div>Value at destination address: 200k sats;</div><div>Rate l=
+imiting params at destination address: none;</div><div>Value at change addr=
+ess a2: 99.8m sats;</div><div>Rate limiting params at change address a2: h0=
+=3D800000, h1=3D800143, a=3D500k, a_remaining=3D300k.</div><div><br></div><=
+div>In order to properly enforce rate limiting, the change address must be =
+rate-limited such that the original rate limit of 500k sats per 144 blocks =
+cannot be exceeded. In this example, the change address a2 were given the s=
+ame rate limiting parameters as the transaction that served as its input. A=
+s a result, from block 800100 up until and including block 800143, a maximu=
+m amount of 300k sats is allowed to be spent from the change address.</div>=
+<div><br></div><div>Example continued:</div><div>a2: 99.8 sats at height=C2=
+=A0800100;</div><div>Rate-limit params: h0=3D800000, h1=3D800143, a=3D500k,=
+ a_remaining=3D300k;</div><div><br></div><div>Transaction t2:</div><div>Inc=
+luded at block height 800200</div><div>Spend: 400k=C2=A0+ fees.</div><div>R=
+ate-limiting params: h0=3D800144, h1=3D800287, a=3D500k, a_remaining=3D100k=
+.<br></div><div><br></div><div><div>Result:</div><div>Value at destination =
+address: 400k sats;</div><div>Rate limiting params at destination address: =
+none;</div><div>Value at change address a3: 99.4m sats;</div><div>Rate limi=
+ting params at change address a3: h0=3D800144, h1=3D800287, a=3D500k, a_rem=
+aining=3D100k.</div><div><br></div><div>Transaction t2 is allowed because i=
+t falls within the next epoch (running from 800144 to 800287) so a spend of=
+ 400k does not violate the constraint of 500k per epoch.</div><div><br></di=
+v><div>As could be seen, the rate limiting parameters are part of the trans=
+action and chosen by the user (or their wallet). This means that the parame=
+ters must be validated to ensure that they do not violate the intended cons=
+traints.</div><div><br></div><div>For instance, this transaction should not=
+ be allowed:</div><div><div>a2: 99.8 sats at height=C2=A0800100;</div><div>=
+Rate-limit params of a2: h0=3D800000, h1=3D800143, a=3D500k, a_remaining=3D=
+300k;</div><div><br></div><div>Transaction t2a:</div><div>Included at block=
+ height 800200;</div><div>Spend: 400k=C2=A0+ fees;</div><div><div>Rate-limi=
+t params: h0=3D800124, h1=3D800267, a=3D500k, a_remaining=3D100k.</div><div=
+><br></div></div><div>This transaction t2a attempts to shift the epoch forw=
+ard by 20 blocks such that it starts at 800124 instead of 800144. Shifting =
+the epoch forward like this must not be allowed because it enables spending=
+ more that the rate limit allows, which is 500k in any epoch of 144 blocks.=
+ It would enable overspending:</div></div><div><br></div><div>t1: spend 200=
+k at 800100 (epoch 1: total: 200k);</div><div>t2a: spend 400k at 800200 (ep=
+och 2: total: 400k);</div><div>t3a: spend 100k at 800201 (epoch 2: total: 5=
+00k);</div><div>t4a: spend 500k at 800268 (epoch 2: total: 1000k, overspend=
+ing for epoch 2).</div><div><br></div><div>Specifying the rate-limiting par=
+ameters explicitly at every transaction allows the user to tighten the spen=
+ding limit by setting tighter limits or for instance by setting a_remainder=
+ to 0 if they wish to enforce not spending more during an epoch.</div><div>=
+<br></div><div>I will stop here because I would like to gauge interest in t=
+his idea first before continuing work on other aspects. Two main pieces of =
+work jump to mind:</div><div><br></div><div>Define all validations;</div><d=
+iv>Describe aggregate behaviour of multiple (rate-limited) inputs, proof th=
+at two rate-limited addresses cannot spend more than the sum of their indiv=
+idual limits.</div><div><br></div><div>Zac</div><div><br></div><div><br></d=
+iv><div><br></div><div><br></div><div><br></div><div><br></div></div></div>
+_______________________________________________<br>
+bitcoin-dev mailing list<br>
+<a href=3D"mailto:bitcoin-dev@lists.linuxfoundation.org" target=3D"_blank">=
+bitcoin-dev@lists.linuxfoundation.org</a><br>
+<a href=3D"https://lists.linuxfoundation.org/mailman/listinfo/bitcoin-dev" =
+rel=3D"noreferrer" target=3D"_blank">https://lists.linuxfoundation.org/mail=
+man/listinfo/bitcoin-dev</a><br>
+</blockquote></div>
+
+--0000000000004cdb6c05c88c2dc3--
+