back to one adr[] slice
all adrs can be converted on the fly and displayed both ways. in the actual UI this shouldn't happen though. Also utxos are sorted and signed properly. utxo selection is still pretty low tech.
This commit is contained in:
parent
fbd17846d4
commit
d8e62f6898
24
shell.go
24
shell.go
@ -212,11 +212,14 @@ func Bal(args []string) error {
|
|||||||
height, _ := SCon.TS.GetDBSyncHeight()
|
height, _ := SCon.TS.GetDBSyncHeight()
|
||||||
|
|
||||||
for i, a := range SCon.TS.Adrs {
|
for i, a := range SCon.TS.Adrs {
|
||||||
fmt.Printf("address %d %s\n", i, a.PkhAdr.String())
|
wa, err := btcutil.NewAddressWitnessPubKeyHash(
|
||||||
|
a.PkhAdr.ScriptAddress(), Params)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
for i, a := range SCon.TS.WitAdrs {
|
fmt.Printf("address %d %s OR %s\n", i, a.PkhAdr.String(), wa.String())
|
||||||
fmt.Printf("address %d %s [WIT]\n", i, a.PkhAdr.String())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Printf("Total known utxos: %d\n", len(allUtxos))
|
fmt.Printf("Total known utxos: %d\n", len(allUtxos))
|
||||||
fmt.Printf("Total spendable coin: %d\n", score)
|
fmt.Printf("Total spendable coin: %d\n", score)
|
||||||
fmt.Printf("DB sync height: %d\n", height)
|
fmt.Printf("DB sync height: %d\n", height)
|
||||||
@ -226,18 +229,18 @@ func Bal(args []string) error {
|
|||||||
// Adr makes a new address.
|
// Adr makes a new address.
|
||||||
func Adr(args []string) error {
|
func Adr(args []string) error {
|
||||||
|
|
||||||
// if there's an arg, make 10 regular adrs
|
// if there's an arg, make 10 adrs
|
||||||
if len(args) > 0 {
|
if len(args) > 0 {
|
||||||
for i := 0; i < 10; i++ {
|
for i := 0; i < 10; i++ {
|
||||||
_, err := SCon.TS.NewAdr(false)
|
_, err := SCon.TS.NewAdr()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// always make one segwit
|
// always make one
|
||||||
a, err := SCon.TS.NewAdr(true)
|
a, err := SCon.TS.NewAdr()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -271,10 +274,7 @@ func Send(args []string) error {
|
|||||||
if len(args) < 2 {
|
if len(args) < 2 {
|
||||||
return fmt.Errorf("need args: ssend amount(satoshis) address wit?")
|
return fmt.Errorf("need args: ssend amount(satoshis) address wit?")
|
||||||
}
|
}
|
||||||
var wit bool // whether to send to p2wpkh
|
|
||||||
if len(args) > 2 {
|
|
||||||
wit = true
|
|
||||||
}
|
|
||||||
amt, err := strconv.ParseInt(args[0], 10, 64)
|
amt, err := strconv.ParseInt(args[0], 10, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -290,7 +290,7 @@ func Send(args []string) error {
|
|||||||
fmt.Printf("send %d to address: %s \n",
|
fmt.Printf("send %d to address: %s \n",
|
||||||
amt, adr.String())
|
amt, adr.String())
|
||||||
|
|
||||||
err = SCon.SendCoins(adr, amt, wit)
|
err = SCon.SendCoins(adr, amt)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -92,7 +92,7 @@ func (s *SPVCon) NewOutgoingTx(tx *wire.MsgTx) error {
|
|||||||
|
|
||||||
// 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(adr btcutil.Address, sendAmt int64, wit bool) error {
|
func (s *SPVCon) SendCoins(adr btcutil.Address, sendAmt int64) error {
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
var score int64
|
var score int64
|
||||||
@ -118,86 +118,98 @@ func (s *SPVCon) SendCoins(adr btcutil.Address, sendAmt int64, wit bool) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// make user specified txout and add to tx
|
|
||||||
txout := wire.NewTxOut(sendAmt, outAdrScript)
|
|
||||||
tx.AddTxOut(txout)
|
|
||||||
////////////////////////////
|
////////////////////////////
|
||||||
|
|
||||||
// generate a utxo slice for your inputs
|
// generate a utxo slice for your inputs
|
||||||
nokori := sendAmt // nokori is how much is needed on input side
|
|
||||||
var ins utxoSlice
|
var ins utxoSlice
|
||||||
|
|
||||||
|
// add utxos until we've had enough
|
||||||
|
nokori := sendAmt // nokori is how much is needed on input side
|
||||||
for _, utxo := range allUtxos {
|
for _, utxo := range allUtxos {
|
||||||
// yeah, lets add this utxo!
|
// yeah, lets add this utxo!
|
||||||
ins = append(ins, *utxo)
|
ins = append(ins, *utxo)
|
||||||
nokori -= utxo.Value
|
nokori -= utxo.Value
|
||||||
if nokori < -10000 { // minimum overage / fee is 1K now
|
if nokori < -10000 { // minimum overage / fee is 10K now
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// sort utxos on the input side
|
// sort utxos on the input side
|
||||||
sort.Sort(ins)
|
sort.Sort(ins)
|
||||||
|
|
||||||
// add all the utxos as txins
|
// make user specified txout and add to tx
|
||||||
for _, in := range ins {
|
txout := wire.NewTxOut(sendAmt, outAdrScript)
|
||||||
var prevPKscript []byte
|
tx.AddTxOut(txout)
|
||||||
|
// see if there's enough left to also add a change output
|
||||||
|
if nokori < -200000 {
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
prevPKscript, err := txscript.PayToAddrScript(
|
changeScript, err := txscript.PayToAddrScript(changeAdr)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
changeOut := wire.NewTxOut((-100000)-nokori, changeScript)
|
||||||
|
tx.AddTxOut(changeOut)
|
||||||
|
}
|
||||||
|
|
||||||
|
// generate previous pkscripts for all the (now sorted) utxos
|
||||||
|
// then make txins with the utxo and prevpk, and insert them into the tx
|
||||||
|
for _, in := range ins {
|
||||||
|
var prevPKs []byte
|
||||||
|
|
||||||
|
// if wit utxo, convert address to generate pkscript
|
||||||
|
if in.IsWit {
|
||||||
|
wa, err := btcutil.NewAddressWitnessPubKeyHash(
|
||||||
|
s.TS.Adrs[in.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[in.KeyIdx].PkhAdr)
|
s.TS.Adrs[in.KeyIdx].PkhAdr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
tx.AddTxIn(wire.NewTxIn(&in.Op, prevPKscript, nil))
|
|
||||||
}
|
}
|
||||||
|
tx.AddTxIn(wire.NewTxIn(&in.Op, prevPKs, nil))
|
||||||
|
}
|
||||||
|
// sort tx -- this only will change txouts since inputs are already sorted
|
||||||
|
txsort.InPlaceSort(tx)
|
||||||
|
|
||||||
// there's enough left to make a change output
|
// tx is ready for signing,
|
||||||
if nokori < -200000 {
|
sigStash := make([][]byte, len(ins))
|
||||||
change, err := s.TS.NewAdr(true) // change is witnessy
|
for i, txin := range tx.TxIn {
|
||||||
|
// pick key
|
||||||
|
child, err := s.TS.rootPrivKey.Child(
|
||||||
|
ins[i].KeyIdx + hdkeychain.HardenedKeyStart)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
priv, err := child.ECPrivKey()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
changeScript, err := txscript.PayToAddrScript(change)
|
// This is where witness based sighash types need to happen
|
||||||
|
// sign into stash
|
||||||
|
sigStash[i], err = txscript.SignatureScript(
|
||||||
|
tx, i, txin.SignatureScript, txscript.SigHashAll, priv, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
changeOut := wire.NewTxOut((-100000)-nokori, changeScript)
|
|
||||||
tx.AddTxOut(changeOut)
|
|
||||||
}
|
}
|
||||||
|
// swap sigs into sigScripts in txins
|
||||||
for _, utxo := range allUtxos {
|
for i, txin := range tx.TxIn {
|
||||||
// generate pkscript to sign
|
txin.SignatureScript = sigStash[i]
|
||||||
prevPKscript, err := txscript.PayToAddrScript(
|
|
||||||
s.TS.Adrs[utxo.KeyIdx].PkhAdr)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
// make new input from this utxo
|
|
||||||
thisInput := wire.NewTxIn(&utxo.Op, prevPKscript, nil)
|
|
||||||
tx.AddTxIn(thisInput)
|
|
||||||
nokori -= utxo.Value
|
|
||||||
if nokori < -10000 { // minimum overage / fee is 1K now
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// there's enough left to make a change output
|
|
||||||
if nokori < -200000 {
|
|
||||||
change, err := s.TS.NewAdr(true) // change is witnessy
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
changeScript, err := txscript.PayToAddrScript(change)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
changeOut := wire.NewTxOut((-100000)-nokori, changeScript)
|
|
||||||
tx.AddTxOut(changeOut)
|
|
||||||
}
|
|
||||||
|
|
||||||
// use txstore method to sign
|
|
||||||
err = s.TS.SignThis(tx)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Printf("tx: %s", TxToString(tx))
|
fmt.Printf("tx: %s", TxToString(tx))
|
||||||
|
@ -21,7 +21,6 @@ type TxStore struct {
|
|||||||
OKMutex sync.Mutex
|
OKMutex sync.Mutex
|
||||||
|
|
||||||
Adrs []MyAdr // endeavouring to acquire capital
|
Adrs []MyAdr // endeavouring to acquire capital
|
||||||
WitAdrs []MyAdr // separate segwit address slice
|
|
||||||
StateDB *bolt.DB // place to write all this down
|
StateDB *bolt.DB // place to write all this down
|
||||||
|
|
||||||
// Params live here, not SCon
|
// Params live here, not SCon
|
||||||
@ -79,7 +78,7 @@ func (t *TxStore) AddTxid(txid *wire.ShaHash, height int32) error {
|
|||||||
|
|
||||||
// ... or I'm gonna fade away
|
// ... or I'm gonna fade away
|
||||||
func (t *TxStore) GimmeFilter() (*bloom.Filter, error) {
|
func (t *TxStore) GimmeFilter() (*bloom.Filter, error) {
|
||||||
if len(t.Adrs) == 0 && len(t.WitAdrs) == 9 {
|
if len(t.Adrs) == 0 {
|
||||||
return nil, fmt.Errorf("no address to filter for")
|
return nil, fmt.Errorf("no address to filter for")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -89,7 +88,7 @@ func (t *TxStore) GimmeFilter() (*bloom.Filter, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
elem := uint32(len(t.Adrs) + len(t.WitAdrs) + len(allUtxos))
|
elem := uint32(len(t.Adrs) + len(allUtxos))
|
||||||
f := bloom.NewFilter(elem, 0, 0.000001, wire.BloomUpdateAll)
|
f := bloom.NewFilter(elem, 0, 0.000001, wire.BloomUpdateAll)
|
||||||
|
|
||||||
// note there could be false positives since we're just looking
|
// note there could be false positives since we're just looking
|
||||||
@ -97,9 +96,6 @@ func (t *TxStore) GimmeFilter() (*bloom.Filter, error) {
|
|||||||
for _, a := range t.Adrs { // add 20-byte pubkeyhash
|
for _, a := range t.Adrs { // add 20-byte pubkeyhash
|
||||||
f.Add(a.PkhAdr.ScriptAddress())
|
f.Add(a.PkhAdr.ScriptAddress())
|
||||||
}
|
}
|
||||||
for _, a := range t.WitAdrs { // add witness 20-byte pubkeyhash
|
|
||||||
f.Add(a.PkhAdr.ScriptAddress())
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, u := range allUtxos {
|
for _, u := range allUtxos {
|
||||||
f.AddOutPoint(&u.Op)
|
f.AddOutPoint(&u.Op)
|
||||||
|
@ -22,8 +22,7 @@ var (
|
|||||||
BKTTxns = []byte("Txns") // all txs we care about, for replays
|
BKTTxns = []byte("Txns") // all txs we care about, for replays
|
||||||
BKTState = []byte("MiscState") // last state of DB
|
BKTState = []byte("MiscState") // last state of DB
|
||||||
// these are in the state bucket
|
// these are in the state bucket
|
||||||
KEYStdKeys = []byte("StdKeys") // number of p2pkh keys used
|
KEYNumKeys = []byte("NumKeys") // number of p2pkh keys used
|
||||||
KEYWitKeys = []byte("WitKeys") // number of p2wpkh keys used
|
|
||||||
KEYTipHeight = []byte("TipHeight") // height synced to
|
KEYTipHeight = []byte("TipHeight") // height synced to
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -53,7 +52,7 @@ func (ts *TxStore) OpenDB(filename string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
numKeysBytes := sta.Get(KEYStdKeys)
|
numKeysBytes := sta.Get(KEYNumKeys)
|
||||||
if numKeysBytes != nil { // NumKeys exists, read into uint32
|
if numKeysBytes != nil { // NumKeys exists, read into uint32
|
||||||
buf := bytes.NewBuffer(numKeysBytes)
|
buf := bytes.NewBuffer(numKeysBytes)
|
||||||
err := binary.Read(buf, binary.BigEndian, &numKeys)
|
err := binary.Read(buf, binary.BigEndian, &numKeys)
|
||||||
@ -68,7 +67,7 @@ func (ts *TxStore) OpenDB(filename string) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
err = sta.Put(KEYStdKeys, buf.Bytes())
|
err = sta.Put(KEYNumKeys, buf.Bytes())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -83,7 +82,7 @@ func (ts *TxStore) OpenDB(filename string) error {
|
|||||||
|
|
||||||
// NewAdr creates a new, never before seen address, and increments the
|
// NewAdr creates a new, never before seen address, and increments the
|
||||||
// DB counter as well as putting it in the ram Adrs store, and returns it
|
// DB counter as well as putting it in the ram Adrs store, and returns it
|
||||||
func (ts *TxStore) NewAdr(wit bool) (btcutil.Address, error) {
|
func (ts *TxStore) NewAdr() (btcutil.Address, error) {
|
||||||
if ts.Param == nil {
|
if ts.Param == nil {
|
||||||
return nil, fmt.Errorf("NewAdr error: nil param")
|
return nil, fmt.Errorf("NewAdr error: nil param")
|
||||||
}
|
}
|
||||||
@ -93,23 +92,6 @@ func (ts *TxStore) NewAdr(wit bool) (btcutil.Address, error) {
|
|||||||
var n uint32
|
var n uint32
|
||||||
var nAdr btcutil.Address
|
var nAdr btcutil.Address
|
||||||
|
|
||||||
if wit {
|
|
||||||
n = uint32(len(ts.WitAdrs))
|
|
||||||
|
|
||||||
// witness keys are another branch down from the rootpriv
|
|
||||||
ephpriv, err := ts.rootPrivKey.Child(1<<30 + hdkeychain.HardenedKeyStart)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
priv, err = ephpriv.Child(n + hdkeychain.HardenedKeyStart)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
nAdr, err = priv.WitnessAddress(ts.Param)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
} else { // regular p2pkh
|
|
||||||
n = uint32(len(ts.Adrs))
|
n = uint32(len(ts.Adrs))
|
||||||
priv, err = ts.rootPrivKey.Child(n + hdkeychain.HardenedKeyStart)
|
priv, err = ts.rootPrivKey.Child(n + hdkeychain.HardenedKeyStart)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -119,7 +101,6 @@ func (ts *TxStore) NewAdr(wit bool) (btcutil.Address, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// total number of keys (now +1) into 4 bytes
|
// total number of keys (now +1) into 4 bytes
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
@ -131,10 +112,9 @@ func (ts *TxStore) NewAdr(wit bool) (btcutil.Address, error) {
|
|||||||
// write to db file
|
// write to db file
|
||||||
err = ts.StateDB.Update(func(btx *bolt.Tx) error {
|
err = ts.StateDB.Update(func(btx *bolt.Tx) error {
|
||||||
sta := btx.Bucket(BKTState)
|
sta := btx.Bucket(BKTState)
|
||||||
if wit {
|
|
||||||
return sta.Put(KEYStdKeys, buf.Bytes())
|
return sta.Put(KEYNumKeys, buf.Bytes())
|
||||||
}
|
|
||||||
return sta.Put(KEYWitKeys, buf.Bytes())
|
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -143,11 +123,9 @@ func (ts *TxStore) NewAdr(wit bool) (btcutil.Address, error) {
|
|||||||
var ma MyAdr
|
var ma MyAdr
|
||||||
ma.PkhAdr = nAdr
|
ma.PkhAdr = nAdr
|
||||||
ma.KeyIdx = n
|
ma.KeyIdx = n
|
||||||
if wit {
|
|
||||||
ts.WitAdrs = append(ts.WitAdrs, ma)
|
|
||||||
} else {
|
|
||||||
ts.Adrs = append(ts.Adrs, ma)
|
ts.Adrs = append(ts.Adrs, ma)
|
||||||
}
|
|
||||||
return nAdr, nil
|
return nAdr, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user