update uspv, add function for height from header
still a bunch of problems getting utxo sets
This commit is contained in:
parent
24afe237db
commit
7dbf4a4a4f
@ -156,6 +156,45 @@ func (s *SPVCon) SendFilter(f *bloom.Filter) {
|
||||
return
|
||||
}
|
||||
|
||||
// HeightFromHeader gives you the block height given a 80 byte block header
|
||||
// seems like looking for the merkle root is the best way to do this
|
||||
func (s *SPVCon) HeightFromHeader(query wire.BlockHeader) (uint32, error) {
|
||||
// start from the most recent and work back in time; even though that's
|
||||
// kind of annoying it's probably a lot faster since things tend to have
|
||||
// happened recently.
|
||||
|
||||
// seek to last header
|
||||
lastPos, err := s.headerFile.Seek(-80, os.SEEK_END)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
height := lastPos / 80
|
||||
|
||||
var current wire.BlockHeader
|
||||
|
||||
for height > 0 {
|
||||
// grab header from disk
|
||||
err = current.Deserialize(s.headerFile)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
// check if merkle roots match
|
||||
if current.MerkleRoot.IsEqual(&query.MerkleRoot) {
|
||||
// if they do, great, return height
|
||||
return uint32(height), nil
|
||||
}
|
||||
// skip back one header (2 because we just read one)
|
||||
_, err = s.headerFile.Seek(-160, os.SEEK_CUR)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
// decrement height
|
||||
height--
|
||||
}
|
||||
// finished for loop without finding match
|
||||
return 0, fmt.Errorf("Header not found on disk")
|
||||
}
|
||||
|
||||
func (s *SPVCon) AskForHeaders() error {
|
||||
var hdr wire.BlockHeader
|
||||
ghdr := wire.NewMsgGetHeaders()
|
||||
@ -201,6 +240,7 @@ func (s *SPVCon) AskForHeaders() error {
|
||||
|
||||
func (s *SPVCon) IngestHeaders(m *wire.MsgHeaders) (bool, error) {
|
||||
var err error
|
||||
// seek to last header
|
||||
_, err = s.headerFile.Seek(-80, os.SEEK_END)
|
||||
if err != nil {
|
||||
return false, err
|
||||
|
@ -77,6 +77,9 @@ func checkMBlock(m *wire.MsgMerkleBlock) ([]*wire.ShaHash, error) {
|
||||
if len(m.Flags) == 0 {
|
||||
return nil, fmt.Errorf("No flag bits")
|
||||
}
|
||||
if len(m.Hashes) < 2 { // nothing but the merkle root
|
||||
return nil, nil // nothin.
|
||||
}
|
||||
var s []merkleNode // the stack
|
||||
var r []*wire.ShaHash // slice to return; txids we care about
|
||||
|
||||
|
@ -39,13 +39,21 @@ func (s *SPVCon) incomingMessageHandler() {
|
||||
if err != nil {
|
||||
log.Printf("Merkle block error: %s\n", err.Error())
|
||||
return
|
||||
// continue
|
||||
}
|
||||
fmt.Printf(" got %d txs ", len(txids))
|
||||
// fmt.Printf(" = got %d txs from block %s\n",
|
||||
// len(txids), m.Header.BlockSha().String())
|
||||
var height uint32
|
||||
if len(txids) > 0 {
|
||||
// make sure block is in our store before adding txs
|
||||
height, err = s.HeightFromHeader(m.Header)
|
||||
if err != nil {
|
||||
log.Printf("Merkle block height error: %s\n", err.Error())
|
||||
continue
|
||||
}
|
||||
}
|
||||
for _, txid := range txids {
|
||||
err := s.TS.AddTxid(txid)
|
||||
err := s.TS.AddTxid(txid, height)
|
||||
if err != nil {
|
||||
log.Printf("Txid store error: %s\n", err.Error())
|
||||
}
|
||||
|
@ -11,10 +11,11 @@ import (
|
||||
)
|
||||
|
||||
type TxStore struct {
|
||||
KnownTxids []*wire.ShaHash
|
||||
Utxos []Utxo // stacks on stacks
|
||||
Sum int64 // racks on racks
|
||||
Adrs []MyAdr // endeavouring to acquire capital
|
||||
OKTxids map[wire.ShaHash]uint32 // known good txids and their heights
|
||||
|
||||
Utxos []Utxo // stacks on stacks
|
||||
Sum int64 // racks on racks
|
||||
Adrs []MyAdr // endeavouring to acquire capital
|
||||
}
|
||||
|
||||
type Utxo struct { // cash money.
|
||||
@ -30,6 +31,12 @@ type MyAdr struct { // an address I have the private key for
|
||||
KeyIdx uint32 // index for private key needed to sign / spend
|
||||
}
|
||||
|
||||
func NewTxStore() TxStore {
|
||||
var txs TxStore
|
||||
txs.OKTxids = make(map[wire.ShaHash]uint32)
|
||||
return txs
|
||||
}
|
||||
|
||||
// add addresses into the TxStore
|
||||
func (t *TxStore) AddAdr(a btcutil.Address, kidx uint32) {
|
||||
var ma MyAdr
|
||||
@ -40,11 +47,11 @@ func (t *TxStore) AddAdr(a btcutil.Address, kidx uint32) {
|
||||
}
|
||||
|
||||
// add txid of interest
|
||||
func (t *TxStore) AddTxid(txid *wire.ShaHash) error {
|
||||
func (t *TxStore) AddTxid(txid *wire.ShaHash, height uint32) error {
|
||||
if txid == nil {
|
||||
return fmt.Errorf("tried to add nil txid")
|
||||
}
|
||||
t.KnownTxids = append(t.KnownTxids, txid)
|
||||
t.OKTxids[*txid] = height
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -62,19 +69,13 @@ func (t *TxStore) GimmeFilter() (*bloom.Filter, error) {
|
||||
|
||||
// Ingest a tx into wallet, dealing with both gains and losses
|
||||
func (t *TxStore) IngestTx(tx *wire.MsgTx) error {
|
||||
var match bool
|
||||
inTxid := tx.TxSha()
|
||||
for _, ktxid := range t.KnownTxids {
|
||||
if inTxid.IsEqual(ktxid) {
|
||||
match = true
|
||||
break // found tx match,
|
||||
}
|
||||
}
|
||||
if !match {
|
||||
height, ok := t.OKTxids[inTxid]
|
||||
if !ok {
|
||||
return fmt.Errorf("we don't care about tx %s", inTxid.String())
|
||||
}
|
||||
|
||||
err := t.AbsorbTx(tx)
|
||||
err := t.AbsorbTx(tx, height)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -87,7 +88,7 @@ func (t *TxStore) IngestTx(tx *wire.MsgTx) error {
|
||||
}
|
||||
|
||||
// Absorb money into wallet from a tx
|
||||
func (t *TxStore) AbsorbTx(tx *wire.MsgTx) error {
|
||||
func (t *TxStore) AbsorbTx(tx *wire.MsgTx, height uint32) error {
|
||||
if tx == nil {
|
||||
return fmt.Errorf("Tried to add nil tx")
|
||||
}
|
||||
@ -102,6 +103,7 @@ func (t *TxStore) AbsorbTx(tx *wire.MsgTx) error {
|
||||
hits++
|
||||
acq += out.Value
|
||||
var newu Utxo
|
||||
newu.AtHeight = height
|
||||
newu.KeyIdx = a.KeyIdx
|
||||
newu.Txo = *out
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user