diff --git a/WALLET.scratch.md b/WALLET.scratch.md index 18303572fd..da5fb6ce9a 100644 --- a/WALLET.scratch.md +++ b/WALLET.scratch.md @@ -74,6 +74,29 @@ Uses `btc-wallet-hook`, with max-gap=3 :: dbug should show re-filled scans: [xpub %1] ``` +### utxo selection +``` +=btc -build-file %/lib/btc/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]) +=val0 200.000 +=val1 500.000 +=val2 30 +=val3 235.000 + +=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 + +=inputs ~[[u(value val0) %0 0] [u(value val1) %0 2] [u(value val2) %0 1] [u(value val3) %1 2]] +(~(single-random-draw sut:bwsl [*walt:bwsl eny1 400.100 100 2]) inputs) +(~(single-random-draw sut:bwsl [*walt:bwsl eny2 400.100 100 2]) inputs)(~(single-random-draw sut:bwsl [*walt:bwsl eny2 400.100 100 2]) inputs) + +``` +Above tests w 2 outputs, total fees with 2 inputs of 27.500. Gives: +1. 500.000 input +2. Inputs 0 and 3 + + ## scrys ``` .^((list @t) %gx /=btc-wallet-store=/scanned/noun) diff --git a/app/btc-wallet-store.hoon b/app/btc-wallet-store.hoon index 272c21170c..17c9833087 100644 --- a/app/btc-wallet-store.hoon +++ b/app/btc-wallet-store.hoon @@ -258,29 +258,4 @@ |=(=utxo:btc value.utxo) add (roll values add) -:: Uses naive random selection. Should switch to branch-and-bound later -:: -++ select-utxos - |= [target=sats w=walt] - ^- (unit (list input)) - =/ is=(list input) - %- zing - %+ turn ~(val by wach.w) - |= =addi - %+ turn ~(tap in utxos.addi) - |=(=utxo:btc [utxo chyg.addi idx.addi]) - (single-random-draw target is) -:: -++ single-random-draw - |= [target=sats is=(list input)] - ^- (unit (list input)) - =| [selected=(list input) total=sats:btc] - =/ rng ~(. og eny.bowl) - |- ?~ is ~ - =^ n rng (rads:rng (lent is)) - =/ i (snag n ((list input) is)) - =/ new-total (add total value.utxo.i) - ?: (gth new-total target) - `[i selected] - $(is t.is, total new-total, selected [i selected]) -- diff --git a/lib/btc-wallet-store.hoon b/lib/btc-wallet-store.hoon index 7350edc84e..c504b260f7 100644 --- a/lib/btc-wallet-store.hoon +++ b/lib/btc-wallet-store.hoon @@ -89,4 +89,70 @@ ?:(?=(%0 chyg) [idx q.nixt.w] [p.nixt.w idx]) -- -- +:: sut: door to select utxos +:: targ: target output amount, not including fees +:: feyb: fee in sats per byte +:: outs: number of outputs +:: +++ sut +|_ [w=walt eny=@uvJ targ=sats feyb=sats outs=@] + ++ meta-weight 10 + ++ output-weight 31 + ++ base-weight + ^- vbytes + %+ add meta-weight + (mul outs output-weight) + ++ input-weight + ^- vbytes + ?. ?=(%bip84 bipt.w) + ~|("Only bech32 wallets supported" !!) + 102 + :: + ++ total-vbytes + |= selected=(list input) + ^- vbytes + %+ add base-weight + (mul input-weight (lent selected)) + :: value of an input after fee + :: 0 if net is <= 0 + :: + ++ net-value + |= val=sats ^- sats + =/ cost (mul input-weight feyb) + ?: (lte val cost) 0 + (sub val cost) + :: Uses naive random selection. Should switch to branch-and-bound later + :: + ++ select-utxos + ^- (unit (list input)) + =/ is=(list input) + %- zing + %+ turn ~(val by wach.w) + |= =addi + %+ turn ~(tap in utxos.addi) + |=(=utxo:btc [utxo chyg.addi idx.addi]) + (single-random-draw is) + :: single-random-draw + :: randomly choose utxos until target is hit + :: only use an input if its net-value > 0 + :: + ++ single-random-draw + |= is=(list input) + ^- (unit (list input)) + =/ rng ~(. og eny) + =/ target (add targ (mul feyb base-weight)) :: add base fees to target + =| [select=(list input) total=sats:btc] + |- ?~ is ~ + =^ n rng (rads:rng (lent is)) + =/ i=input (snag n ((list input) is)) + =/ net-val (net-value value.utxo.i) + =? select (gth net-val 0) [i select] :: select if net-value > 0 + =/ new-total (add total net-val) + ?: (gte new-total target) `select + %= $ + is (oust [n 1] ((list input) is)) + total new-total + == + :: + -- -- diff --git a/sur/btc.hoon b/sur/btc.hoon index c7618bc982..17a179b975 100644 --- a/sur/btc.hoon +++ b/sur/btc.hoon @@ -6,6 +6,7 @@ +$ address ?(legacy-address bech32-address) +$ bipt $?(%bip44 %bip49 %bip84) +$ sats @ud ++$ vbytes @ud +$ hash256 [wid=%32 dat=@ux] +$ hash160 [wid=%20 dat=@ux] +$ hash ?(hash256 hash160)