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"
|
||||
"log"
|
||||
"os"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
@ -147,6 +148,13 @@ func Shellparse(cmdslice []string) error {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
if cmd == "sweep" {
|
||||
err = Sweep(args)
|
||||
if err != nil {
|
||||
fmt.Printf("sweep error: %s\n", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
if cmd == "txs" {
|
||||
err = Txs(args)
|
||||
if err != nil {
|
||||
@ -202,10 +210,17 @@ func Bal(args []string) error {
|
||||
return fmt.Errorf("Can't get balance, spv connection broken")
|
||||
}
|
||||
fmt.Printf(" ----- Account Balance ----- \n")
|
||||
allUtxos, err := SCon.TS.GetAllUtxos()
|
||||
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))
|
||||
|
||||
var score, confScore int64
|
||||
for i, u := range allUtxos {
|
||||
fmt.Printf("\tutxo %d height %d %s key:%d amt %d",
|
||||
@ -221,6 +236,10 @@ func Bal(args []string) error {
|
||||
}
|
||||
height, _ := SCon.TS.GetDBSyncHeight()
|
||||
|
||||
atx, err := SCon.TS.GetAllTxs()
|
||||
|
||||
stxos, err := SCon.TS.GetAllStxos()
|
||||
|
||||
for i, a := range SCon.TS.Adrs {
|
||||
wa, err := btcutil.NewAddressWitnessPubKeyHash(
|
||||
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("Total known utxos: %d\n", len(allUtxos))
|
||||
fmt.Printf("Total known txs: %d\n", len(atx))
|
||||
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("DB sync height: %d\n", height)
|
||||
return nil
|
||||
@ -268,13 +288,62 @@ func Adr(args []string) error {
|
||||
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.
|
||||
// syntax: fan adr numOutputs valOutputs witty
|
||||
func Fan(args []string) error {
|
||||
if len(args) < 3 {
|
||||
return fmt.Errorf("fan syntax: fan adr numOutputs valOutputs")
|
||||
}
|
||||
|
||||
adr, err := btcutil.DecodeAddress(args[0], SCon.TS.Param)
|
||||
if err != nil {
|
||||
fmt.Printf("error parsing %s as address\t", args[0])
|
||||
@ -296,9 +365,7 @@ func Fan(args []string) error {
|
||||
adrs[i] = adr
|
||||
amts[i] = valOutputs + i
|
||||
}
|
||||
|
||||
return SCon.SendCoins(adrs, amts)
|
||||
|
||||
}
|
||||
|
||||
// Send sends coins.
|
||||
|
@ -189,7 +189,6 @@ func (s *SPVCon) GetDataHandler(m *wire.MsgGetData) {
|
||||
log.Printf("error getting tx %s: %s",
|
||||
thing.Hash.String(), err.Error())
|
||||
}
|
||||
fmt.Printf(TxToString(tx))
|
||||
s.outMsgQueue <- tx
|
||||
sent++
|
||||
continue
|
||||
|
@ -68,12 +68,22 @@ func (s utxoSlice) Less(i, j int) bool {
|
||||
return bytes.Compare(ihash[:], jhash[:]) == -1
|
||||
}
|
||||
|
||||
type utxoByAmt []Utxo
|
||||
type SortableUtxoSlice []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 }
|
||||
// utxoByAmts get sorted by utxo value. also put unconfirmed last
|
||||
func (s SortableUtxoSlice) Len() int { return len(s) }
|
||||
func (s SortableUtxoSlice) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
|
||||
|
||||
// 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 {
|
||||
txid := tx.TxSha()
|
||||
@ -97,6 +107,84 @@ func (s *SPVCon) NewOutgoingTx(tx *wire.MsgTx) error {
|
||||
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
|
||||
// wit makes it into p2wpkh. Which is not yet spendable.
|
||||
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 {
|
||||
return err
|
||||
}
|
||||
var allUtxos utxoByAmt
|
||||
var allUtxos SortableUtxoSlice
|
||||
// start with utxos sorted by value.
|
||||
|
||||
for _, utxo := range rawUtxos {
|
||||
score += utxo.Value
|
||||
allUtxos = append(allUtxos, *utxo)
|
||||
}
|
||||
// smallest and unconfirmed last (because it's reversed)
|
||||
sort.Sort(sort.Reverse(allUtxos))
|
||||
|
||||
// sort.Reverse(allUtxos)
|
||||
for _, u := range allUtxos {
|
||||
fmt.Printf("%d ", u.Value)
|
||||
}
|
||||
for _, amt := range sendAmts {
|
||||
totalSend += amt
|
||||
}
|
||||
@ -272,10 +359,8 @@ func (s *SPVCon) SendCoins(adrs []btcutil.Address, sendAmts []int64) error {
|
||||
|
||||
}
|
||||
|
||||
fmt.Printf("tx: %s", TxToString(tx))
|
||||
buf := bytes.NewBuffer(make([]byte, 0, tx.SerializeSize()))
|
||||
tx.SerializeWitness(buf)
|
||||
fmt.Printf("tx: %x\n", buf.Bytes())
|
||||
// fmt.Printf("tx: %s", TxToString(tx))
|
||||
// buf := bytes.NewBuffer(make([]byte, 0, tx.SerializeSize()))
|
||||
|
||||
// send it out on the wire. hope it gets there.
|
||||
// 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
|
||||
}
|
||||
}
|
||||
// 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
|
||||
// convert regular address to witness address. (split adrs later)
|
||||
wa, err := btcutil.NewAddressWitnessPubKeyHash(
|
||||
@ -383,28 +389,30 @@ func (ts *TxStore) Ingest(tx *wire.MsgTx, height int32) (uint32, error) {
|
||||
return hits, err
|
||||
}
|
||||
|
||||
wPKscript, err := txscript.PayToAddrScript(wa)
|
||||
wPKscripts[i], err = txscript.PayToAddrScript(wa)
|
||||
if err != nil {
|
||||
return hits, err
|
||||
}
|
||||
aPKscript, err := txscript.PayToAddrScript(adr.PkhAdr)
|
||||
aPKscripts[i], err = txscript.PayToAddrScript(adr.PkhAdr)
|
||||
if err != nil {
|
||||
return hits, err
|
||||
}
|
||||
}
|
||||
|
||||
// iterate through all outputs of this tx, see if we gain
|
||||
for i, out := range tx.TxOut {
|
||||
// iterate through all outputs of this tx, see if we gain
|
||||
for i, out := range tx.TxOut {
|
||||
for j, ascr := range aPKscripts {
|
||||
|
||||
// detect p2wpkh
|
||||
witBool := false
|
||||
if bytes.Equal(out.PkScript, wPKscript) {
|
||||
if bytes.Equal(out.PkScript, wPKscripts[j]) {
|
||||
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
|
||||
newu.AtHeight = height
|
||||
newu.KeyIdx = adr.KeyIdx
|
||||
newu.KeyIdx = ts.Adrs[j].KeyIdx
|
||||
newu.Value = out.Value
|
||||
newu.IsWit = witBool // copy witness version from pkscript
|
||||
var newop wire.OutPoint
|
||||
@ -417,7 +425,7 @@ func (ts *TxStore) Ingest(tx *wire.MsgTx, height int32) (uint32, error) {
|
||||
}
|
||||
nUtxoBytes = append(nUtxoBytes, b)
|
||||
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