simplify boltdb ingest
This commit is contained in:
parent
a14b9a9e70
commit
df04a73e1a
56
shell.go
56
shell.go
@ -206,7 +206,7 @@ func Bal(args []string) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var score int64
|
||||
var score, confScore int64
|
||||
for i, u := range allUtxos {
|
||||
fmt.Printf("\tutxo %d height %d %s key:%d amt %d",
|
||||
i, u.AtHeight, u.Op.String(), u.KeyIdx, u.Value)
|
||||
@ -215,6 +215,9 @@ func Bal(args []string) error {
|
||||
}
|
||||
fmt.Printf("\n")
|
||||
score += u.Value
|
||||
if u.AtHeight != 0 {
|
||||
confScore += u.Value
|
||||
}
|
||||
}
|
||||
height, _ := SCon.TS.GetDBSyncHeight()
|
||||
|
||||
@ -228,7 +231,7 @@ func Bal(args []string) error {
|
||||
}
|
||||
|
||||
fmt.Printf("Total known utxos: %d\n", len(allUtxos))
|
||||
fmt.Printf("Total spendable coin: %d\n", score)
|
||||
fmt.Printf("Total coin: %d confirmed: %d\n", score, confScore)
|
||||
fmt.Printf("DB sync height: %d\n", height)
|
||||
return nil
|
||||
}
|
||||
@ -266,20 +269,22 @@ func Adr(args []string) error {
|
||||
}
|
||||
|
||||
// Fan generates a bunch of fanout. Only for testing, can be expensive.
|
||||
// syntax: fan numOutputs valOutputs witty
|
||||
// syntax: fan adr numOutputs valOutputs witty
|
||||
func Fan(args []string) error {
|
||||
if len(args) < 3 {
|
||||
return fmt.Errorf("fan syntax: fan numOutputs valOutputs witty")
|
||||
return fmt.Errorf("fan syntax: fan adr numOutputs valOutputs")
|
||||
}
|
||||
numOutputs, err := strconv.ParseInt(args[0], 10, 64)
|
||||
|
||||
adr, err := btcutil.DecodeAddress(args[0], SCon.TS.Param)
|
||||
if err != nil {
|
||||
fmt.Printf("error parsing %s as address\t", args[0])
|
||||
return err
|
||||
}
|
||||
numOutputs, err := strconv.ParseInt(args[1], 10, 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
valOutputs, err := strconv.ParseInt(args[1], 10, 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
wittynum, err := strconv.ParseInt(args[2], 10, 64)
|
||||
valOutputs, err := strconv.ParseInt(args[2], 10, 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -287,21 +292,8 @@ func Fan(args []string) error {
|
||||
adrs := make([]btcutil.Address, numOutputs)
|
||||
amts := make([]int64, numOutputs)
|
||||
|
||||
oAdr, err := SCon.TS.NewAdr()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for i := int64(0); i < numOutputs; i++ {
|
||||
if wittynum != 0 {
|
||||
wAdr, err := btcutil.NewAddressWitnessPubKeyHash(
|
||||
oAdr.ScriptAddress(), SCon.TS.Param)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
adrs[i] = wAdr
|
||||
} else {
|
||||
adrs[i] = oAdr
|
||||
}
|
||||
adrs[i] = adr
|
||||
amts[i] = valOutputs + i
|
||||
}
|
||||
|
||||
@ -331,21 +323,21 @@ func Send(args []string) error {
|
||||
}
|
||||
// need args, fail
|
||||
if len(args) < 2 {
|
||||
return fmt.Errorf("need args: ssend amount(satoshis) address wit?")
|
||||
return fmt.Errorf("need args: ssend address amount(satoshis) wit?")
|
||||
}
|
||||
|
||||
amt, err := strconv.ParseInt(args[0], 10, 64)
|
||||
adr, err := btcutil.DecodeAddress(args[0], SCon.TS.Param)
|
||||
if err != nil {
|
||||
fmt.Printf("error parsing %s as address\t", args[0])
|
||||
return err
|
||||
}
|
||||
amt, err := strconv.ParseInt(args[1], 10, 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if amt < 1000 {
|
||||
return fmt.Errorf("can't send %d, too small", amt)
|
||||
}
|
||||
adr, err := btcutil.DecodeAddress(args[1], SCon.TS.Param)
|
||||
if err != nil {
|
||||
fmt.Printf("error parsing %s as address\t", args[1])
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Printf("send %d to address: %s \n",
|
||||
amt, adr.String())
|
||||
|
||||
|
@ -43,7 +43,7 @@ func (s *SPVCon) Rebroadcast() {
|
||||
return
|
||||
}
|
||||
|
||||
// make utxo slices sortable
|
||||
// make utxo slices sortable -- same as txsort
|
||||
type utxoSlice []Utxo
|
||||
|
||||
// Sort utxos just like txins -- Len, Less, Swap
|
||||
@ -68,6 +68,13 @@ func (s utxoSlice) Less(i, j int) bool {
|
||||
return bytes.Compare(ihash[:], jhash[:]) == -1
|
||||
}
|
||||
|
||||
type utxoByAmt []Utxo
|
||||
|
||||
// utxoByAmts get sorted by utxo value
|
||||
func (s utxoByAmt) Len() int { return len(s) }
|
||||
func (s utxoByAmt) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
|
||||
func (s utxoByAmt) Less(i, j int) bool { return s[i].Value < s[j].Value }
|
||||
|
||||
func (s *SPVCon) NewOutgoingTx(tx *wire.MsgTx) error {
|
||||
txid := tx.TxSha()
|
||||
// assign height of zero for txs we create
|
||||
@ -99,14 +106,22 @@ func (s *SPVCon) SendCoins(adrs []btcutil.Address, sendAmts []int64) error {
|
||||
var err error
|
||||
var score, totalSend, fee int64
|
||||
dustCutoff := int64(20000) // below this amount, just give to miners
|
||||
satPerByte := int64(30) // satoshis per byte fee; have as arg later
|
||||
allUtxos, err := s.TS.GetAllUtxos()
|
||||
satPerByte := int64(80) // satoshis per byte fee; have as arg later
|
||||
rawUtxos, err := s.TS.GetAllUtxos()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var allUtxos utxoByAmt
|
||||
// start with utxos sorted by value.
|
||||
|
||||
for _, utxo := range allUtxos {
|
||||
for _, utxo := range rawUtxos {
|
||||
score += utxo.Value
|
||||
allUtxos = append(allUtxos, *utxo)
|
||||
}
|
||||
sort.Sort(sort.Reverse(allUtxos))
|
||||
// sort.Reverse(allUtxos)
|
||||
for _, u := range allUtxos {
|
||||
fmt.Printf("%d ", u.Value)
|
||||
}
|
||||
for _, amt := range sendAmts {
|
||||
totalSend += amt
|
||||
@ -136,8 +151,13 @@ func (s *SPVCon) SendCoins(adrs []btcutil.Address, sendAmts []int64) error {
|
||||
// add utxos until we've had enough
|
||||
nokori := totalSend // nokori is how much is needed on input side
|
||||
for _, utxo := range allUtxos {
|
||||
// skip unconfirmed. Or de-prioritize?
|
||||
// if utxo.AtHeight == 0 {
|
||||
// continue
|
||||
// }
|
||||
|
||||
// yeah, lets add this utxo!
|
||||
ins = append(ins, *utxo)
|
||||
ins = append(ins, utxo)
|
||||
// as we add utxos, fill in sigscripts
|
||||
// generate previous pkscripts (subscritpt?) for all utxos
|
||||
// then make txins with the utxo and prevpk, and insert them into the tx
|
||||
@ -205,6 +225,11 @@ func (s *SPVCon) SendCoins(adrs []btcutil.Address, sendAmts []int64) error {
|
||||
// tx is ready for signing,
|
||||
sigStash := make([][]byte, len(ins))
|
||||
witStash := make([][][]byte, len(ins))
|
||||
|
||||
// generate tx-wide hashCache for segwit stuff
|
||||
// middle index number doesn't matter for sighashAll.
|
||||
hCache := txscript.CalcHashCache(tx, 0, txscript.SigHashAll)
|
||||
|
||||
for i, txin := range tx.TxIn {
|
||||
// pick key
|
||||
child, err := s.TS.rootPrivKey.Child(
|
||||
@ -221,7 +246,7 @@ func (s *SPVCon) SendCoins(adrs []btcutil.Address, sendAmts []int64) error {
|
||||
// sign into stash
|
||||
if ins[i].IsWit {
|
||||
witStash[i], err = txscript.WitnessScript(
|
||||
tx, i, ins[i].Value, txin.SignatureScript,
|
||||
tx, hCache, i, ins[i].Value, txin.SignatureScript,
|
||||
txscript.SigHashAll, priv, true)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -368,16 +368,14 @@ func (ts *TxStore) Ingest(tx *wire.MsgTx, height int32) (uint32, error) {
|
||||
spentOPs := make([][]byte, len(tx.TxIn))
|
||||
// before entering into db, serialize all inputs of the ingested tx
|
||||
for i, txin := range tx.TxIn {
|
||||
nOP, err := outPointToBytes(&txin.PreviousOutPoint)
|
||||
spentOPs[i], err = outPointToBytes(&txin.PreviousOutPoint)
|
||||
if err != nil {
|
||||
return hits, err
|
||||
}
|
||||
spentOPs[i] = nOP
|
||||
}
|
||||
// also generate PKscripts for all addresses (maybe keep storing these?)
|
||||
for _, adr := range ts.Adrs {
|
||||
// iterate through all our addresses
|
||||
|
||||
// convert regular address to witness address. (split adrs later)
|
||||
wa, err := btcutil.NewAddressWitnessPubKeyHash(
|
||||
adr.PkhAdr.ScriptAddress(), ts.Param)
|
||||
@ -437,59 +435,49 @@ func (ts *TxStore) Ingest(tx *wire.MsgTx, height int32) (uint32, error) {
|
||||
// first see if we lose utxos
|
||||
// iterate through duffel bag and look for matches
|
||||
// this makes us lose money, which is regrettable, but we need to know.
|
||||
|
||||
var delOPs [][]byte
|
||||
// fmt.Printf("%d nOP to iterate over\n", len(spentOPs))
|
||||
// var delOPs [][]byte
|
||||
for _, nOP := range spentOPs {
|
||||
duf.ForEach(func(k, v []byte) error {
|
||||
if bytes.Equal(k, nOP) { // matched, we lost utxo
|
||||
fmt.Printf("will delete point %x\n", k)
|
||||
hits++
|
||||
// do all this just to figure out value we lost
|
||||
x := make([]byte, len(k)+len(v))
|
||||
copy(x, k)
|
||||
y := make([]byte, len(k))
|
||||
// mark utxo for deletion
|
||||
copy(y, k)
|
||||
delOPs = append(delOPs, y)
|
||||
|
||||
copy(x[len(k):], v)
|
||||
lostTxo, err := UtxoFromBytes(x)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// after marking for deletion, save stxo to old bucket
|
||||
var st Stxo // generate spent txo
|
||||
st.Utxo = lostTxo // assign outpoint
|
||||
st.SpendHeight = height // spent at height
|
||||
st.SpendTxid = tx.TxSha() // spent by txid
|
||||
stxb, err := st.ToBytes() // serialize
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = old.Put(k, stxb) // write k:v outpoint:stxo bytes
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// store this relevant tx
|
||||
sha := tx.TxSha()
|
||||
var buf bytes.Buffer
|
||||
tx.SerializeWitness(&buf) // always store witness version
|
||||
err = txns.Put(sha.Bytes(), buf.Bytes())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil // matched utxo k, won't match another
|
||||
v := duf.Get(nOP)
|
||||
if v != nil {
|
||||
hits++
|
||||
// do all this just to figure out value we lost
|
||||
x := make([]byte, len(nOP)+len(v))
|
||||
copy(x, nOP)
|
||||
copy(x[len(nOP):], v)
|
||||
lostTxo, err := UtxoFromBytes(x)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil // no match
|
||||
})
|
||||
// delete after done with foreach
|
||||
|
||||
// after marking for deletion, save stxo to old bucket
|
||||
var st Stxo // generate spent txo
|
||||
st.Utxo = lostTxo // assign outpoint
|
||||
st.SpendHeight = height // spent at height
|
||||
st.SpendTxid = tx.TxSha() // spent by txid
|
||||
stxb, err := st.ToBytes() // serialize
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = old.Put(nOP, stxb) // write nOP:v outpoint:stxo bytes
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// store this relevant tx
|
||||
sha := tx.TxSha()
|
||||
var buf bytes.Buffer
|
||||
tx.SerializeWitness(&buf) // always store witness version
|
||||
err = txns.Put(sha.Bytes(), buf.Bytes())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// stash for deletion
|
||||
// delOPs = append(delOPs, nOP)
|
||||
}
|
||||
}
|
||||
for _, y := range delOPs {
|
||||
fmt.Printf("deleting outpoint %x\n", y)
|
||||
err = duf.Delete(y)
|
||||
|
||||
//delete everything even if it doesn't exist!
|
||||
for _, dOP := range spentOPs {
|
||||
err = duf.Delete(dOP)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user