mirror of
https://github.com/urbit/shrub.git
synced 2024-12-19 16:51:42 +03:00
refactor UTXO selection
This commit is contained in:
parent
63dd964a1b
commit
a8cd63265d
@ -4,7 +4,7 @@ Creates dummy inputs and outputs. Builds a TX with them.
|
|||||||
```
|
```
|
||||||
=btc -build-file %/lib/btc/hoon
|
=btc -build-file %/lib/btc/hoon
|
||||||
=bwsl -build-file %/lib/btc-wallet-store/hoon
|
=bwsl -build-file %/lib/btc-wallet-store/hoon
|
||||||
=u (utxo:btc [pos=0 (hash256:btc [wid=32 dat=0xc493.f6f1.4668.5f76.b44f.0c77.ca88.120c.b8bc.89f5.34fe.69b6.8288.27b9.74e6.8849]) height=3 value=0])
|
=u (utxo:btc [pos=0 (hash256:btc [wid=32 dat=0xc493.f6f1.4668.5f76.b44f.0c77.ca88.120c.b8bc.89f5.34fe.69b6.8288.27b9.74e6.8849]) height=3 value=0 ~])
|
||||||
=val0 200.000
|
=val0 200.000
|
||||||
=val1 500.000
|
=val1 500.000
|
||||||
=val2 30
|
=val2 30
|
||||||
@ -12,10 +12,10 @@ Creates dummy inputs and outputs. Builds a TX with them.
|
|||||||
|
|
||||||
=eny1 0v3uc.iuebi.5qilc.l8d87.c1k6n.7iksq.nkobs.8s5he.raq40.9ff0b.5tj3u.kjtg7.aq59e.hatv7.oioam.mlsr4.pqqcd.cnbjn.pnpi2.1m5rt.k4scg
|
=eny1 0v3uc.iuebi.5qilc.l8d87.c1k6n.7iksq.nkobs.8s5he.raq40.9ff0b.5tj3u.kjtg7.aq59e.hatv7.oioam.mlsr4.pqqcd.cnbjn.pnpi2.1m5rt.k4scg
|
||||||
=eny2 0v1gt.mc4ca.lfs0m.q1dal.lqobu.mmlbd.2umnp.lj9dr.4pf4s.pvclr.dps96.4a6i8.rt6n9.krp0r.11kqu.ckqe4.1tmat.gr754.463aj.a4b41.jj7qg
|
=eny2 0v1gt.mc4ca.lfs0m.q1dal.lqobu.mmlbd.2umnp.lj9dr.4pf4s.pvclr.dps96.4a6i8.rt6n9.krp0r.11kqu.ckqe4.1tmat.gr754.463aj.a4b41.jj7qg
|
||||||
|
=w *walt:bwsl
|
||||||
|
=w w(bipt %bip84, confs 6)
|
||||||
=inputs ~[[u(value val0) %0 0] [u(value val1) %0 2] [u(value val2) %0 1] [u(value val3) %1 2]]
|
=inputs ~[[u(value val0) %0 0] [u(value val1) %0 2] [u(value val2) %0 1] [u(value val3) %1 2]]
|
||||||
=outputs ~[[[%bech32 'bc1q59u5epktervh6fxqay2dlph0wxu9hjnx6v8n66'] value=200.100] [[%bech32 'bc1qlwd7mw33uea5m8r2lsnsrkc7gp2qynrxsfxpfm'] value=200.000]]
|
=outputs ~[[[%bech32 'bc1q59u5epktervh6fxqay2dlph0wxu9hjnx6v8n66'] value=200.100] [[%bech32 'bc1qlwd7mw33uea5m8r2lsnsrkc7gp2qynrxsfxpfm'] value=200.000]]
|
||||||
=w *walt:bwsl
|
|
||||||
=w w(bipt %bip84)
|
|
||||||
|
|
||||||
(~(single-random-draw sut:bwsl [w eny1 923 ~ 100 outputs]) inputs)
|
(~(single-random-draw sut:bwsl [w eny1 923 ~ 100 outputs]) inputs)
|
||||||
(~(single-random-draw sut:bwsl [w eny2 923 ~ 100 outputs]) inputs)
|
(~(single-random-draw sut:bwsl [w eny2 923 ~ 100 outputs]) inputs)
|
||||||
|
@ -55,7 +55,7 @@
|
|||||||
def ~(. (default-agent this %|) bowl)
|
def ~(. (default-agent this %|) bowl)
|
||||||
hc ~(. +> bowl)
|
hc ~(. +> bowl)
|
||||||
::
|
::
|
||||||
++ on-init
|
++ on-initb
|
||||||
^- (quip card _this)
|
^- (quip card _this)
|
||||||
~& > '%btc-wallet-hook initialized'
|
~& > '%btc-wallet-hook initialized'
|
||||||
:_ this(fam-limit.state fam-limit:defaults)
|
:_ this(fam-limit.state fam-limit:defaults)
|
||||||
|
@ -128,16 +128,43 @@
|
|||||||
::
|
::
|
||||||
%generate-address
|
%generate-address
|
||||||
(generate-address +.act)
|
(generate-address +.act)
|
||||||
|
:: TODO: end to end tests
|
||||||
|
:: %generate-txbu
|
||||||
|
:: - get txbu and change amount
|
||||||
|
:: - if txbu is blank, fail
|
||||||
|
:: - if change is blank, send txbu as update
|
||||||
|
:: - if change:
|
||||||
|
:: - generate new change address
|
||||||
|
:: - add that address+change value to the txbu
|
||||||
|
:: - send txbu update
|
||||||
|
:: - send address update
|
||||||
|
:: - send a request for info on the address (watch it)
|
||||||
::
|
::
|
||||||
%generate-txbu
|
%generate-txbu
|
||||||
=+ w=(~(get by walts) xpub.act)
|
=+ uw=(~(get by walts) xpub.act)
|
||||||
?~ w ~&(>>> "btc-wallet-store: non-existent xpub" `state)
|
?~ uw
|
||||||
=/ t=(unit txbu)
|
~|("btc-wallet-store: non-existent xpub" !!)
|
||||||
%~ select-utxos sut
|
?. scanned.u.uw
|
||||||
[u.w eny.bowl last-block payee.act feyb.act txos.act]
|
~|("btc-wallet-store: wallet not scanned yet" !!)
|
||||||
?~ t ~&(>>> "btc-wallet-store: insufficient balance" `state)
|
=/ [tb=(unit txbu) chng=(unit sats)]
|
||||||
:_ state
|
%~ with-change sut
|
||||||
~[(send-update [%generate-txbu xpub.act u.t])]
|
[u.uw eny.bowl last-block payee.act feyb.act txos.act]
|
||||||
|
?~ tb ~&(>>> "btc-wallet-store: insufficient balance" `state)
|
||||||
|
:: if no change, just return txbu
|
||||||
|
::
|
||||||
|
?~ chng
|
||||||
|
[~[(send-update [%generate-txbu xpub.act u.tb])] state]
|
||||||
|
=/ [addr=address:btc =idx w=walt]
|
||||||
|
~(gen-address wad u.uw %1)
|
||||||
|
=+ new-txbu=(~(add-output txb u.tb) addr u.chng)
|
||||||
|
:_ state(walts (~(put by walts) xpub.act w))
|
||||||
|
:~ (send-update [%generate-txbu xpub.act new-txbu])
|
||||||
|
(send-update [%generate-address xpub.act addr ~])
|
||||||
|
%+ send-request ~[requests-path]
|
||||||
|
:* %address-info last-block
|
||||||
|
addr xpub.act %1 idx
|
||||||
|
==
|
||||||
|
==
|
||||||
::
|
::
|
||||||
%add-history-entry
|
%add-history-entry
|
||||||
:: TODO
|
:: TODO
|
||||||
@ -294,6 +321,7 @@
|
|||||||
::
|
::
|
||||||
++ generate-address
|
++ generate-address
|
||||||
|= [=xpub =chyg =peta]
|
|= [=xpub =chyg =peta]
|
||||||
|
^- (quip card _state)
|
||||||
=+ uw=(~(get by walts) xpub)
|
=+ uw=(~(get by walts) xpub)
|
||||||
?~ uw
|
?~ uw
|
||||||
~|("btc-wallet-store: non-existent xpub" !!)
|
~|("btc-wallet-store: non-existent xpub" !!)
|
||||||
|
@ -71,6 +71,30 @@
|
|||||||
(fall max-gap max-gap:defaults)
|
(fall max-gap max-gap:defaults)
|
||||||
(fall confs confs:defaults)
|
(fall confs confs:defaults)
|
||||||
==
|
==
|
||||||
|
:: txb: transaction builder helpers
|
||||||
|
::
|
||||||
|
++ txb
|
||||||
|
|_ t=txbu
|
||||||
|
++ value
|
||||||
|
^- [in=sats out=sats]
|
||||||
|
:- %+ roll
|
||||||
|
%+ turn txis.t
|
||||||
|
|=(=txi value.utxo.txi)
|
||||||
|
add
|
||||||
|
%+ roll
|
||||||
|
(turn txos.t |=(=txo value.txo))
|
||||||
|
add
|
||||||
|
::
|
||||||
|
++ fee
|
||||||
|
=/ [in=sats out=sats] value
|
||||||
|
(sub in out)
|
||||||
|
::
|
||||||
|
++ add-output
|
||||||
|
|= [=address:btc value=sats]
|
||||||
|
^- txbu
|
||||||
|
=/ ntxo=txo [address value]
|
||||||
|
t(txos [ntxo txos.t])
|
||||||
|
--
|
||||||
:: wad: door for processing walts (wallets)
|
:: wad: door for processing walts (wallets)
|
||||||
:: parameterized on a walt and it's chyg account
|
:: parameterized on a walt and it's chyg account
|
||||||
::
|
::
|
||||||
@ -139,6 +163,7 @@
|
|||||||
|_ [w=walt eny=@uvJ last-block=@ud payee=(unit ship) =feyb txos=(list txo)]
|
|_ [w=walt eny=@uvJ last-block=@ud payee=(unit ship) =feyb txos=(list txo)]
|
||||||
++ meta-weight 10
|
++ meta-weight 10
|
||||||
++ output-weight 31
|
++ output-weight 31
|
||||||
|
++ n-txos (lent txos)
|
||||||
::
|
::
|
||||||
++ target-value
|
++ target-value
|
||||||
^- sats
|
^- sats
|
||||||
@ -146,9 +171,10 @@
|
|||||||
|=([a=sats b=sats] (add a b))
|
|=([a=sats b=sats] (add a b))
|
||||||
::
|
::
|
||||||
++ base-weight
|
++ base-weight
|
||||||
|
|= num-txos=@ud
|
||||||
^- vbytes
|
^- vbytes
|
||||||
%+ add meta-weight
|
%+ add meta-weight
|
||||||
(mul (lent txos) output-weight)
|
(mul num-txos output-weight)
|
||||||
::
|
::
|
||||||
++ input-weight
|
++ input-weight
|
||||||
^- vbytes
|
^- vbytes
|
||||||
@ -156,10 +182,15 @@
|
|||||||
~|("Only bech32 wallets supported" !!)
|
~|("Only bech32 wallets supported" !!)
|
||||||
102
|
102
|
||||||
::
|
::
|
||||||
|
++ min-tx-fee
|
||||||
|
^- sats
|
||||||
|
%+ mul feyb
|
||||||
|
(add (base-weight 1) input-weight)
|
||||||
|
::
|
||||||
++ total-vbytes
|
++ total-vbytes
|
||||||
|= selected=(list input)
|
|= selected=(list input)
|
||||||
^- vbytes
|
^- vbytes
|
||||||
%+ add base-weight
|
%+ add (base-weight n-txos)
|
||||||
(mul input-weight (lent selected))
|
(mul input-weight (lent selected))
|
||||||
:: value of an input after fee
|
:: value of an input after fee
|
||||||
:: 0 if net is <= 0
|
:: 0 if net is <= 0
|
||||||
@ -169,15 +200,32 @@
|
|||||||
=/ cost (mul input-weight feyb)
|
=/ cost (mul input-weight feyb)
|
||||||
?: (lte val cost) 0
|
?: (lte val cost) 0
|
||||||
(sub val cost)
|
(sub val cost)
|
||||||
|
::
|
||||||
:: +spendable: whether utxo has enough confs to spend
|
:: +spendable: whether utxo has enough confs to spend
|
||||||
::
|
::
|
||||||
++ spendable
|
++ spendable
|
||||||
|= =utxo:btc ^- ?
|
|= =utxo:btc ^- ?
|
||||||
(gte (num-confs last-block utxo) confs.w)
|
(gte (num-confs last-block utxo) confs.w)
|
||||||
|
:: +with-change:
|
||||||
|
:: - choose UTXOs, if there are enough
|
||||||
|
:: - return txbu and amount of change (if any)
|
||||||
|
::
|
||||||
|
++ with-change
|
||||||
|
^- [tb=(unit txbu) chng=(unit sats)]
|
||||||
|
=+ tb=select-utxos
|
||||||
|
?~ tb [~ ~]
|
||||||
|
=+ fee=~(fee txb u.tb)
|
||||||
|
=/ costs=sats :: cost of this tx + sending another
|
||||||
|
%+ add min-tx-fee
|
||||||
|
(mul feyb vbytes.u.tb)
|
||||||
|
?. (gth fee costs)
|
||||||
|
[tb ~]
|
||||||
|
:- tb
|
||||||
|
`(sub fee costs)
|
||||||
:: Uses naive random selection. Should switch to branch-and-bound later.
|
:: Uses naive random selection. Should switch to branch-and-bound later.
|
||||||
::
|
::
|
||||||
++ select-utxos
|
++ select-utxos
|
||||||
|^ ^- (unit =txbu)
|
|^ ^- (unit txbu)
|
||||||
=/ is=(unit (list input))
|
=/ is=(unit (list input))
|
||||||
%- single-random-draw
|
%- single-random-draw
|
||||||
%- zing
|
%- zing
|
||||||
@ -209,7 +257,7 @@
|
|||||||
|= is=(list input)
|
|= is=(list input)
|
||||||
^- (unit (list input))
|
^- (unit (list input))
|
||||||
=/ rng ~(. og eny)
|
=/ rng ~(. og eny)
|
||||||
=/ target (add target-value (mul feyb base-weight)) :: add base fees to target
|
=/ target (add target-value (mul feyb (base-weight n-txos))) :: add base fees to target
|
||||||
=| [select=(list input) total=sats:btc]
|
=| [select=(list input) total=sats:btc]
|
||||||
|- ?: =(~ is) ~
|
|- ?: =(~ is) ~
|
||||||
=^ n rng (rads:rng (lent is))
|
=^ n rng (rads:rng (lent is))
|
||||||
|
Loading…
Reference in New Issue
Block a user