more stress testing stuff
This commit is contained in:
parent
df04a73e1a
commit
f9a740d392
79
shell.go
79
shell.go
@ -5,6 +5,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
|
"sort"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
@ -147,6 +148,13 @@ func Shellparse(cmdslice []string) error {
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
if cmd == "sweep" {
|
||||||
|
err = Sweep(args)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("sweep error: %s\n", err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
if cmd == "txs" {
|
if cmd == "txs" {
|
||||||
err = Txs(args)
|
err = Txs(args)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -202,10 +210,17 @@ func Bal(args []string) error {
|
|||||||
return fmt.Errorf("Can't get balance, spv connection broken")
|
return fmt.Errorf("Can't get balance, spv connection broken")
|
||||||
}
|
}
|
||||||
fmt.Printf(" ----- Account Balance ----- \n")
|
fmt.Printf(" ----- Account Balance ----- \n")
|
||||||
allUtxos, err := SCon.TS.GetAllUtxos()
|
rawUtxos, err := SCon.TS.GetAllUtxos()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
var allUtxos uspv.SortableUtxoSlice
|
||||||
|
for _, utxo := range rawUtxos {
|
||||||
|
allUtxos = append(allUtxos, *utxo)
|
||||||
|
}
|
||||||
|
// smallest and unconfirmed last (because it's reversed)
|
||||||
|
sort.Sort(sort.Reverse(allUtxos))
|
||||||
|
|
||||||
var score, confScore int64
|
var score, confScore int64
|
||||||
for i, u := range allUtxos {
|
for i, u := range allUtxos {
|
||||||
fmt.Printf("\tutxo %d height %d %s key:%d amt %d",
|
fmt.Printf("\tutxo %d height %d %s key:%d amt %d",
|
||||||
@ -221,6 +236,10 @@ func Bal(args []string) error {
|
|||||||
}
|
}
|
||||||
height, _ := SCon.TS.GetDBSyncHeight()
|
height, _ := SCon.TS.GetDBSyncHeight()
|
||||||
|
|
||||||
|
atx, err := SCon.TS.GetAllTxs()
|
||||||
|
|
||||||
|
stxos, err := SCon.TS.GetAllStxos()
|
||||||
|
|
||||||
for i, a := range SCon.TS.Adrs {
|
for i, a := range SCon.TS.Adrs {
|
||||||
wa, err := btcutil.NewAddressWitnessPubKeyHash(
|
wa, err := btcutil.NewAddressWitnessPubKeyHash(
|
||||||
a.PkhAdr.ScriptAddress(), Params)
|
a.PkhAdr.ScriptAddress(), Params)
|
||||||
@ -229,8 +248,9 @@ func Bal(args []string) error {
|
|||||||
}
|
}
|
||||||
fmt.Printf("address %d %s OR %s\n", i, a.PkhAdr.String(), wa.String())
|
fmt.Printf("address %d %s OR %s\n", i, a.PkhAdr.String(), wa.String())
|
||||||
}
|
}
|
||||||
|
fmt.Printf("Total known txs: %d\n", len(atx))
|
||||||
fmt.Printf("Total known utxos: %d\n", len(allUtxos))
|
fmt.Printf("Known utxos: %d\tPreviously spent txos: %d\n",
|
||||||
|
len(allUtxos), len(stxos))
|
||||||
fmt.Printf("Total coin: %d confirmed: %d\n", score, confScore)
|
fmt.Printf("Total coin: %d confirmed: %d\n", score, confScore)
|
||||||
fmt.Printf("DB sync height: %d\n", height)
|
fmt.Printf("DB sync height: %d\n", height)
|
||||||
return nil
|
return nil
|
||||||
@ -268,13 +288,62 @@ func Adr(args []string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Sweep sends every confirmed uxto in your wallet to an address.
|
||||||
|
// it does them all individually to there are a lot of txs generated.
|
||||||
|
// syntax: sweep adr
|
||||||
|
func Sweep(args []string) error {
|
||||||
|
if len(args) < 2 {
|
||||||
|
return fmt.Errorf("sweep syntax: sweep adr")
|
||||||
|
}
|
||||||
|
|
||||||
|
adr, err := btcutil.DecodeAddress(args[0], SCon.TS.Param)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("error parsing %s as address\t", args[0])
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
numTxs, err := strconv.ParseInt(args[1], 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if numTxs < 1 {
|
||||||
|
return fmt.Errorf("can't send %d txs", numTxs)
|
||||||
|
}
|
||||||
|
|
||||||
|
rawUtxos, err := SCon.TS.GetAllUtxos()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
var allUtxos uspv.SortableUtxoSlice
|
||||||
|
for _, utxo := range rawUtxos {
|
||||||
|
allUtxos = append(allUtxos, *utxo)
|
||||||
|
}
|
||||||
|
// smallest and unconfirmed last (because it's reversed)
|
||||||
|
sort.Sort(sort.Reverse(allUtxos))
|
||||||
|
|
||||||
|
for i, u := range allUtxos {
|
||||||
|
if u.AtHeight != 0 {
|
||||||
|
err = SCon.SendOne(allUtxos[i], adr)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
numTxs--
|
||||||
|
if numTxs == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf("spent all confirmed utxos; not enough by %d\n", numTxs)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// Fan generates a bunch of fanout. Only for testing, can be expensive.
|
// Fan generates a bunch of fanout. Only for testing, can be expensive.
|
||||||
// syntax: fan adr numOutputs valOutputs witty
|
// syntax: fan adr numOutputs valOutputs witty
|
||||||
func Fan(args []string) error {
|
func Fan(args []string) error {
|
||||||
if len(args) < 3 {
|
if len(args) < 3 {
|
||||||
return fmt.Errorf("fan syntax: fan adr numOutputs valOutputs")
|
return fmt.Errorf("fan syntax: fan adr numOutputs valOutputs")
|
||||||
}
|
}
|
||||||
|
|
||||||
adr, err := btcutil.DecodeAddress(args[0], SCon.TS.Param)
|
adr, err := btcutil.DecodeAddress(args[0], SCon.TS.Param)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("error parsing %s as address\t", args[0])
|
fmt.Printf("error parsing %s as address\t", args[0])
|
||||||
@ -296,9 +365,7 @@ func Fan(args []string) error {
|
|||||||
adrs[i] = adr
|
adrs[i] = adr
|
||||||
amts[i] = valOutputs + i
|
amts[i] = valOutputs + i
|
||||||
}
|
}
|
||||||
|
|
||||||
return SCon.SendCoins(adrs, amts)
|
return SCon.SendCoins(adrs, amts)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send sends coins.
|
// Send sends coins.
|
||||||
|
@ -189,7 +189,6 @@ func (s *SPVCon) GetDataHandler(m *wire.MsgGetData) {
|
|||||||
log.Printf("error getting tx %s: %s",
|
log.Printf("error getting tx %s: %s",
|
||||||
thing.Hash.String(), err.Error())
|
thing.Hash.String(), err.Error())
|
||||||
}
|
}
|
||||||
fmt.Printf(TxToString(tx))
|
|
||||||
s.outMsgQueue <- tx
|
s.outMsgQueue <- tx
|
||||||
sent++
|
sent++
|
||||||
continue
|
continue
|
||||||
|
@ -68,12 +68,22 @@ func (s utxoSlice) Less(i, j int) bool {
|
|||||||
return bytes.Compare(ihash[:], jhash[:]) == -1
|
return bytes.Compare(ihash[:], jhash[:]) == -1
|
||||||
}
|
}
|
||||||
|
|
||||||
type utxoByAmt []Utxo
|
type SortableUtxoSlice []Utxo
|
||||||
|
|
||||||
// utxoByAmts get sorted by utxo value
|
// utxoByAmts get sorted by utxo value. also put unconfirmed last
|
||||||
func (s utxoByAmt) Len() int { return len(s) }
|
func (s SortableUtxoSlice) Len() int { return len(s) }
|
||||||
func (s utxoByAmt) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
|
func (s SortableUtxoSlice) 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 }
|
|
||||||
|
// height 0 means your lesser
|
||||||
|
func (s SortableUtxoSlice) Less(i, j int) bool {
|
||||||
|
if s[i].AtHeight == 0 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if s[j].AtHeight == 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return s[i].Value < s[j].Value
|
||||||
|
}
|
||||||
|
|
||||||
func (s *SPVCon) NewOutgoingTx(tx *wire.MsgTx) error {
|
func (s *SPVCon) NewOutgoingTx(tx *wire.MsgTx) error {
|
||||||
txid := tx.TxSha()
|
txid := tx.TxSha()
|
||||||
@ -97,6 +107,84 @@ func (s *SPVCon) NewOutgoingTx(tx *wire.MsgTx) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *SPVCon) SendOne(u Utxo, adr btcutil.Address) error {
|
||||||
|
// fixed fee
|
||||||
|
fee := int64(5000)
|
||||||
|
|
||||||
|
sendAmt := u.Value - fee
|
||||||
|
tx := wire.NewMsgTx() // make new tx
|
||||||
|
// add single output
|
||||||
|
outAdrScript, err := txscript.PayToAddrScript(adr)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// make user specified txout and add to tx
|
||||||
|
txout := wire.NewTxOut(sendAmt, outAdrScript)
|
||||||
|
tx.AddTxOut(txout)
|
||||||
|
|
||||||
|
var prevPKs []byte
|
||||||
|
if u.IsWit {
|
||||||
|
tx.Flags = 0x01
|
||||||
|
wa, err := btcutil.NewAddressWitnessPubKeyHash(
|
||||||
|
s.TS.Adrs[u.KeyIdx].PkhAdr.ScriptAddress(), s.TS.Param)
|
||||||
|
prevPKs, err = txscript.PayToAddrScript(wa)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} else { // otherwise generate directly
|
||||||
|
prevPKs, err = txscript.PayToAddrScript(
|
||||||
|
s.TS.Adrs[u.KeyIdx].PkhAdr)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tx.AddTxIn(wire.NewTxIn(&u.Op, prevPKs, nil))
|
||||||
|
|
||||||
|
var sig []byte
|
||||||
|
var wit [][]byte
|
||||||
|
hCache := txscript.CalcHashCache(tx, 0, txscript.SigHashAll)
|
||||||
|
|
||||||
|
child, err := s.TS.rootPrivKey.Child(u.KeyIdx + hdkeychain.HardenedKeyStart)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
priv, err := child.ECPrivKey()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is where witness based sighash types need to happen
|
||||||
|
// sign into stash
|
||||||
|
if u.IsWit {
|
||||||
|
wit, err = txscript.WitnessScript(
|
||||||
|
tx, hCache, 0, u.Value, tx.TxIn[0].SignatureScript,
|
||||||
|
txscript.SigHashAll, priv, true)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
sig, err = txscript.SignatureScript(
|
||||||
|
tx, 0, tx.TxIn[0].SignatureScript,
|
||||||
|
txscript.SigHashAll, priv, true)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// swap sigs into sigScripts in txins
|
||||||
|
|
||||||
|
if sig != nil {
|
||||||
|
tx.TxIn[0].SignatureScript = sig
|
||||||
|
}
|
||||||
|
if wit != nil {
|
||||||
|
tx.TxIn[0].Witness = wit
|
||||||
|
tx.TxIn[0].SignatureScript = nil
|
||||||
|
}
|
||||||
|
return s.NewOutgoingTx(tx)
|
||||||
|
}
|
||||||
|
|
||||||
// SendCoins does send coins, but it's very rudimentary
|
// SendCoins does send coins, but it's very rudimentary
|
||||||
// wit makes it into p2wpkh. Which is not yet spendable.
|
// wit makes it into p2wpkh. Which is not yet spendable.
|
||||||
func (s *SPVCon) SendCoins(adrs []btcutil.Address, sendAmts []int64) error {
|
func (s *SPVCon) SendCoins(adrs []btcutil.Address, sendAmts []int64) error {
|
||||||
@ -111,18 +199,17 @@ func (s *SPVCon) SendCoins(adrs []btcutil.Address, sendAmts []int64) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
var allUtxos utxoByAmt
|
var allUtxos SortableUtxoSlice
|
||||||
// start with utxos sorted by value.
|
// start with utxos sorted by value.
|
||||||
|
|
||||||
for _, utxo := range rawUtxos {
|
for _, utxo := range rawUtxos {
|
||||||
score += utxo.Value
|
score += utxo.Value
|
||||||
allUtxos = append(allUtxos, *utxo)
|
allUtxos = append(allUtxos, *utxo)
|
||||||
}
|
}
|
||||||
|
// smallest and unconfirmed last (because it's reversed)
|
||||||
sort.Sort(sort.Reverse(allUtxos))
|
sort.Sort(sort.Reverse(allUtxos))
|
||||||
|
|
||||||
// sort.Reverse(allUtxos)
|
// sort.Reverse(allUtxos)
|
||||||
for _, u := range allUtxos {
|
|
||||||
fmt.Printf("%d ", u.Value)
|
|
||||||
}
|
|
||||||
for _, amt := range sendAmts {
|
for _, amt := range sendAmts {
|
||||||
totalSend += amt
|
totalSend += amt
|
||||||
}
|
}
|
||||||
@ -272,10 +359,8 @@ func (s *SPVCon) SendCoins(adrs []btcutil.Address, sendAmts []int64) error {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Printf("tx: %s", TxToString(tx))
|
// fmt.Printf("tx: %s", TxToString(tx))
|
||||||
buf := bytes.NewBuffer(make([]byte, 0, tx.SerializeSize()))
|
// buf := bytes.NewBuffer(make([]byte, 0, tx.SerializeSize()))
|
||||||
tx.SerializeWitness(buf)
|
|
||||||
fmt.Printf("tx: %x\n", buf.Bytes())
|
|
||||||
|
|
||||||
// send it out on the wire. hope it gets there.
|
// send it out on the wire. hope it gets there.
|
||||||
// we should deal with rejects. Don't yet.
|
// we should deal with rejects. Don't yet.
|
||||||
|
@ -373,8 +373,14 @@ func (ts *TxStore) Ingest(tx *wire.MsgTx, height int32) (uint32, error) {
|
|||||||
return hits, err
|
return hits, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// also generate PKscripts for all addresses (maybe keep storing these?)
|
|
||||||
for _, adr := range ts.Adrs {
|
// go through txouts, and then go through addresses to match
|
||||||
|
|
||||||
|
// generate PKscripts for all addresses
|
||||||
|
wPKscripts := make([][]byte, len(ts.Adrs))
|
||||||
|
aPKscripts := make([][]byte, len(ts.Adrs))
|
||||||
|
|
||||||
|
for i, adr := range ts.Adrs {
|
||||||
// iterate through all our addresses
|
// iterate through all our addresses
|
||||||
// convert regular address to witness address. (split adrs later)
|
// convert regular address to witness address. (split adrs later)
|
||||||
wa, err := btcutil.NewAddressWitnessPubKeyHash(
|
wa, err := btcutil.NewAddressWitnessPubKeyHash(
|
||||||
@ -383,28 +389,30 @@ func (ts *TxStore) Ingest(tx *wire.MsgTx, height int32) (uint32, error) {
|
|||||||
return hits, err
|
return hits, err
|
||||||
}
|
}
|
||||||
|
|
||||||
wPKscript, err := txscript.PayToAddrScript(wa)
|
wPKscripts[i], err = txscript.PayToAddrScript(wa)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return hits, err
|
return hits, err
|
||||||
}
|
}
|
||||||
aPKscript, err := txscript.PayToAddrScript(adr.PkhAdr)
|
aPKscripts[i], err = txscript.PayToAddrScript(adr.PkhAdr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return hits, err
|
return hits, err
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// iterate through all outputs of this tx, see if we gain
|
// iterate through all outputs of this tx, see if we gain
|
||||||
for i, out := range tx.TxOut {
|
for i, out := range tx.TxOut {
|
||||||
|
for j, ascr := range aPKscripts {
|
||||||
|
|
||||||
// detect p2wpkh
|
// detect p2wpkh
|
||||||
witBool := false
|
witBool := false
|
||||||
if bytes.Equal(out.PkScript, wPKscript) {
|
if bytes.Equal(out.PkScript, wPKscripts[j]) {
|
||||||
witBool = true
|
witBool = true
|
||||||
}
|
}
|
||||||
|
|
||||||
if bytes.Equal(out.PkScript, aPKscript) || witBool { // new utxo found
|
if bytes.Equal(out.PkScript, ascr) || witBool { // new utxo found
|
||||||
var newu Utxo // create new utxo and copy into it
|
var newu Utxo // create new utxo and copy into it
|
||||||
newu.AtHeight = height
|
newu.AtHeight = height
|
||||||
newu.KeyIdx = adr.KeyIdx
|
newu.KeyIdx = ts.Adrs[j].KeyIdx
|
||||||
newu.Value = out.Value
|
newu.Value = out.Value
|
||||||
newu.IsWit = witBool // copy witness version from pkscript
|
newu.IsWit = witBool // copy witness version from pkscript
|
||||||
var newop wire.OutPoint
|
var newop wire.OutPoint
|
||||||
@ -417,7 +425,7 @@ func (ts *TxStore) Ingest(tx *wire.MsgTx, height int32) (uint32, error) {
|
|||||||
}
|
}
|
||||||
nUtxoBytes = append(nUtxoBytes, b)
|
nUtxoBytes = append(nUtxoBytes, b)
|
||||||
hits++
|
hits++
|
||||||
// break // keep looking! address re-use in same tx
|
break // txos can match only 1 script
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user