add fanout. fix boltdb weirdness.
again with keys / values within the bolttx acting weird. it wasn't deleting utxos that had been spent by the ingested tx. it'd do the first 30 then stop. Deferred deletion and copied the serialized utxo. Not sure which of those fixed it. Maybe both.
This commit is contained in:
parent
bc4cf5ba80
commit
dd1f2c00fe
59
shell.go
59
shell.go
@ -140,6 +140,13 @@ func Shellparse(cmdslice []string) error {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
if cmd == "fan" {
|
||||
err = Fan(args)
|
||||
if err != nil {
|
||||
fmt.Printf("fan error: %s\n", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
if cmd == "txs" {
|
||||
err = Txs(args)
|
||||
if err != nil {
|
||||
@ -238,6 +245,14 @@ func Adr(args []string) error {
|
||||
}
|
||||
}
|
||||
}
|
||||
if len(args) > 1 {
|
||||
for i := 0; i < 1000; i++ {
|
||||
_, err := SCon.TS.NewAdr()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// always make one
|
||||
a, err := SCon.TS.NewAdr()
|
||||
@ -250,6 +265,50 @@ func Adr(args []string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Fan generates a bunch of fanout. Only for testing, can be expensive.
|
||||
// syntax: fan numOutputs valOutputs witty
|
||||
func Fan(args []string) error {
|
||||
if len(args) < 3 {
|
||||
return fmt.Errorf("fan syntax: fan numOutputs valOutputs witty")
|
||||
}
|
||||
numOutputs, err := strconv.ParseInt(args[0], 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)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
amts[i] = valOutputs + i
|
||||
}
|
||||
|
||||
return SCon.SendCoins(adrs, amts)
|
||||
|
||||
}
|
||||
|
||||
// Send sends coins.
|
||||
func Send(args []string) error {
|
||||
if SCon.RBytes == 0 {
|
||||
|
@ -160,14 +160,17 @@ func (s *SPVCon) SendCoins(adrs []btcutil.Address, sendAmts []int64) error {
|
||||
}
|
||||
tx.AddTxIn(wire.NewTxIn(&utxo.Op, prevPKs, nil))
|
||||
nokori -= utxo.Value
|
||||
// if nokori is positive, don't bother checking fee yet.
|
||||
if nokori < 0 {
|
||||
fee = EstFee(tx, satPerByte)
|
||||
if nokori < -fee { // done adding utxos: nokori below negative est. fee
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// see if there's enough left to also add a change output
|
||||
if nokori < -dustCutoff {
|
||||
|
||||
changeOld, err := s.TS.NewAdr() // change is witnessy
|
||||
if err != nil {
|
||||
return err
|
||||
@ -187,6 +190,9 @@ func (s *SPVCon) SendCoins(adrs []btcutil.Address, sendAmts []int64) error {
|
||||
tx.AddTxOut(changeOut)
|
||||
fee = EstFee(tx, satPerByte)
|
||||
changeOut.Value = -(nokori + fee)
|
||||
if changeOut.Value < dustCutoff {
|
||||
// remove last output (change) : not worth it
|
||||
tx.TxOut = tx.TxOut[:len(tx.TxOut)-1]
|
||||
}
|
||||
|
||||
// sort utxos on the input side. use this instead of txsort
|
||||
|
@ -353,7 +353,6 @@ func (ts *TxStore) PopulateAdrs(lastKey uint32) error {
|
||||
func (ts *TxStore) Ingest(tx *wire.MsgTx, height int32) (uint32, error) {
|
||||
var hits uint32
|
||||
var err error
|
||||
var spentOPs [][]byte
|
||||
var nUtxoBytes [][]byte
|
||||
|
||||
// tx has been OK'd by SPV; check tx sanity
|
||||
@ -366,13 +365,14 @@ func (ts *TxStore) Ingest(tx *wire.MsgTx, height int32) (uint32, error) {
|
||||
// note that you can't check signatures; this is SPV.
|
||||
// 0 conf SPV means pretty much nothing. Anyone can say anything.
|
||||
|
||||
spentOPs := make([][]byte, len(tx.TxIn))
|
||||
// before entering into db, serialize all inputs of the ingested tx
|
||||
for _, txin := range tx.TxIn {
|
||||
for i, txin := range tx.TxIn {
|
||||
nOP, err := outPointToBytes(&txin.PreviousOutPoint)
|
||||
if err != nil {
|
||||
return hits, err
|
||||
}
|
||||
spentOPs = append(spentOPs, nOP)
|
||||
spentOPs[i] = nOP
|
||||
}
|
||||
// also generate PKscripts for all addresses (maybe keep storing these?)
|
||||
for _, adr := range ts.Adrs {
|
||||
@ -419,7 +419,7 @@ func (ts *TxStore) Ingest(tx *wire.MsgTx, height int32) (uint32, error) {
|
||||
}
|
||||
nUtxoBytes = append(nUtxoBytes, b)
|
||||
hits++
|
||||
break // only one match
|
||||
// break // keep looking! address re-use in same tx
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -437,24 +437,25 @@ 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))
|
||||
for _, nOP := range spentOPs {
|
||||
duf.ForEach(func(k, v []byte) error {
|
||||
if bytes.Equal(k, nOP) { // matched, we lost utxo
|
||||
// do all this just to figure out value we lost
|
||||
x := make([]byte, len(k)+len(v))
|
||||
copy(x, k)
|
||||
// mark utxos for deletion
|
||||
delOPs = append(delOPs, x)
|
||||
copy(x[len(k):], v)
|
||||
lostTxo, err := UtxoFromBytes(x)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
hits++
|
||||
// then delete the utxo from duf, save to old
|
||||
err = duf.Delete(k)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// after deletion, save stxo to old bucket
|
||||
|
||||
// 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
|
||||
@ -480,6 +481,13 @@ func (ts *TxStore) Ingest(tx *wire.MsgTx, height int32) (uint32, error) {
|
||||
}
|
||||
return nil // no match
|
||||
})
|
||||
// delete after done with foreach
|
||||
for _, k := range delOPs {
|
||||
err = duf.Delete(k)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
} // done losing utxos, next gain utxos
|
||||
// next add all new utxos to db, this is quick as the work is above
|
||||
for _, ub := range nUtxoBytes {
|
||||
|
Loading…
Reference in New Issue
Block a user