update uspv, add function for height from header

still a bunch of problems getting utxo sets
This commit is contained in:
Tadge Dryja 2016-01-19 01:33:58 -08:00
parent 24afe237db
commit 7dbf4a4a4f
4 changed files with 71 additions and 18 deletions

@ -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