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
|
return nil
|
||||||
}
|
}
|
||||||
|
if cmd == "fan" {
|
||||||
|
err = Fan(args)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("fan error: %s\n", err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
if cmd == "txs" {
|
if cmd == "txs" {
|
||||||
err = Txs(args)
|
err = Txs(args)
|
||||||
if err != nil {
|
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
|
// always make one
|
||||||
a, err := SCon.TS.NewAdr()
|
a, err := SCon.TS.NewAdr()
|
||||||
@ -250,6 +265,50 @@ func Adr(args []string) error {
|
|||||||
return nil
|
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.
|
// Send sends coins.
|
||||||
func Send(args []string) error {
|
func Send(args []string) error {
|
||||||
if SCon.RBytes == 0 {
|
if SCon.RBytes == 0 {
|
||||||
|
@ -160,33 +160,39 @@ func (s *SPVCon) SendCoins(adrs []btcutil.Address, sendAmts []int64) error {
|
|||||||
}
|
}
|
||||||
tx.AddTxIn(wire.NewTxIn(&utxo.Op, prevPKs, nil))
|
tx.AddTxIn(wire.NewTxIn(&utxo.Op, prevPKs, nil))
|
||||||
nokori -= utxo.Value
|
nokori -= utxo.Value
|
||||||
fee = EstFee(tx, satPerByte)
|
// if nokori is positive, don't bother checking fee yet.
|
||||||
if nokori < -fee { // done adding utxos: nokori below negative est. fee
|
if nokori < 0 {
|
||||||
break
|
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
|
// 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
|
|
||||||
}
|
|
||||||
changeAdr, err := btcutil.NewAddressWitnessPubKeyHash(
|
|
||||||
changeOld.ScriptAddress(), s.TS.Param)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
changeScript, err := txscript.PayToAddrScript(changeAdr)
|
changeOld, err := s.TS.NewAdr() // change is witnessy
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
changeAdr, err := btcutil.NewAddressWitnessPubKeyHash(
|
||||||
|
changeOld.ScriptAddress(), s.TS.Param)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
changeOut := wire.NewTxOut(0, changeScript)
|
changeScript, err := txscript.PayToAddrScript(changeAdr)
|
||||||
tx.AddTxOut(changeOut)
|
if err != nil {
|
||||||
fee = EstFee(tx, satPerByte)
|
return err
|
||||||
changeOut.Value = -(nokori + fee)
|
}
|
||||||
|
|
||||||
|
changeOut := wire.NewTxOut(0, changeScript)
|
||||||
|
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
|
// 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) {
|
func (ts *TxStore) Ingest(tx *wire.MsgTx, height int32) (uint32, error) {
|
||||||
var hits uint32
|
var hits uint32
|
||||||
var err error
|
var err error
|
||||||
var spentOPs [][]byte
|
|
||||||
var nUtxoBytes [][]byte
|
var nUtxoBytes [][]byte
|
||||||
|
|
||||||
// tx has been OK'd by SPV; check tx sanity
|
// 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.
|
// note that you can't check signatures; this is SPV.
|
||||||
// 0 conf SPV means pretty much nothing. Anyone can say anything.
|
// 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
|
// 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)
|
nOP, err := outPointToBytes(&txin.PreviousOutPoint)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return hits, err
|
return hits, err
|
||||||
}
|
}
|
||||||
spentOPs = append(spentOPs, nOP)
|
spentOPs[i] = nOP
|
||||||
}
|
}
|
||||||
// also generate PKscripts for all addresses (maybe keep storing these?)
|
// also generate PKscripts for all addresses (maybe keep storing these?)
|
||||||
for _, adr := range ts.Adrs {
|
for _, adr := range ts.Adrs {
|
||||||
@ -419,7 +419,7 @@ func (ts *TxStore) Ingest(tx *wire.MsgTx, height int32) (uint32, error) {
|
|||||||
}
|
}
|
||||||
nUtxoBytes = append(nUtxoBytes, b)
|
nUtxoBytes = append(nUtxoBytes, b)
|
||||||
hits++
|
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
|
// first see if we lose utxos
|
||||||
// iterate through duffel bag and look for matches
|
// iterate through duffel bag and look for matches
|
||||||
// this makes us lose money, which is regrettable, but we need to know.
|
// 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 {
|
for _, nOP := range spentOPs {
|
||||||
duf.ForEach(func(k, v []byte) error {
|
duf.ForEach(func(k, v []byte) error {
|
||||||
if bytes.Equal(k, nOP) { // matched, we lost utxo
|
if bytes.Equal(k, nOP) { // matched, we lost utxo
|
||||||
// do all this just to figure out value we lost
|
// do all this just to figure out value we lost
|
||||||
x := make([]byte, len(k)+len(v))
|
x := make([]byte, len(k)+len(v))
|
||||||
copy(x, k)
|
copy(x, k)
|
||||||
|
// mark utxos for deletion
|
||||||
|
delOPs = append(delOPs, x)
|
||||||
copy(x[len(k):], v)
|
copy(x[len(k):], v)
|
||||||
lostTxo, err := UtxoFromBytes(x)
|
lostTxo, err := UtxoFromBytes(x)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
hits++
|
hits++
|
||||||
// then delete the utxo from duf, save to old
|
|
||||||
err = duf.Delete(k)
|
// after marking for deletion, save stxo to old bucket
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
// after deletion, save stxo to old bucket
|
|
||||||
var st Stxo // generate spent txo
|
var st Stxo // generate spent txo
|
||||||
st.Utxo = lostTxo // assign outpoint
|
st.Utxo = lostTxo // assign outpoint
|
||||||
st.SpendHeight = height // spent at height
|
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
|
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
|
} // done losing utxos, next gain utxos
|
||||||
// next add all new utxos to db, this is quick as the work is above
|
// next add all new utxos to db, this is quick as the work is above
|
||||||
for _, ub := range nUtxoBytes {
|
for _, ub := range nUtxoBytes {
|
||||||
|
Loading…
Reference in New Issue
Block a user