can sync with segnet in hard mode

lots of changes but they seem to work
This commit is contained in:
Tadge Dryja 2016-02-15 22:13:17 -08:00
parent a955a428a7
commit 0d3639435f
7 changed files with 135 additions and 40 deletions

@ -86,7 +86,7 @@ func newLightningChannel(wallet *LightningWallet, events chainntnfs.ChainNotifie
return nil, err
}
_, multiSigIndex := findScriptOutputIndex(state.FundingTx, fundingPkScript)
lc.fundingTxIn = wire.NewTxIn(wire.NewOutPoint(&fundingTxId, multiSigIndex), nil)
lc.fundingTxIn = wire.NewTxIn(wire.NewOutPoint(&fundingTxId, multiSigIndex), nil, nil)
lc.fundingP2SH = fundingPkScript
return lc, nil

@ -529,7 +529,7 @@ func (l *LightningWallet) handleFundingReserveRequest(req *initFundingReserveMsg
// Empty sig script, we'll actually sign if this reservation is
// queued up to be completed (the other side accepts).
outPoint := wire.NewOutPoint(coin.Hash(), coin.Index())
ourContribution.Inputs[i] = wire.NewTxIn(outPoint, nil)
ourContribution.Inputs[i] = wire.NewTxIn(outPoint, nil, nil)
}
l.coinSelectMtx.Unlock()
@ -794,7 +794,7 @@ func (l *LightningWallet) handleContributionMsg(req *addContributionMsg) {
// since the outputs are cannonically sorted.
fundingNTxid := fundingTx.TxSha() // NOTE: assumes testnet-L
_, multiSigIndex := findScriptOutputIndex(fundingTx, multiSigOut.PkScript)
fundingTxIn := wire.NewTxIn(wire.NewOutPoint(&fundingNTxid, multiSigIndex), nil)
fundingTxIn := wire.NewTxIn(wire.NewOutPoint(&fundingNTxid, multiSigIndex), nil, nil)
// With the funding tx complete, create both commitment transactions.
initialBalance := ourContribution.FundingAmount

@ -4,11 +4,12 @@ import (
"bytes"
"encoding/binary"
"fmt"
"io"
"io/ioutil"
"github.com/btcsuite/btcd/btcec"
"github.com/btcsuite/btcd/wire"
"github.com/btcsuite/btcutil"
"io"
"io/ioutil"
)
var MAX_SLICE_LENGTH = 65535
@ -21,12 +22,12 @@ type CommitHeight uint64
// Subsatoshi amount (Micro-Satoshi, 1/1000th)
// Should be a signed int to account for negative fees
//
//
// "In any science-fiction movie, anywhere in the galaxy, currency is referred
// to as 'credits.'"
// --Sam Humphries. Ebert, Roger (1999). Ebert's bigger little movie
// glossary. Andrews McMeel. p. 172.
//
//
// https:// en.wikipedia.org/wiki/List_of_fictional_currencies
// https:// en.wikipedia.org/wiki/Fictional_currency#Trends_in_the_use_of_fictional_currencies
// http:// tvtropes.org/pmwiki/pmwiki.php/Main/WeWillSpendCreditsInTheFuture
@ -557,7 +558,7 @@ func readElement(r io.Reader, element interface{}) error {
var txins []*wire.TxIn
for i := uint8(0); i < numScripts; i++ {
outpoint := new(wire.OutPoint)
txin := wire.NewTxIn(outpoint, nil)
txin := wire.NewTxIn(outpoint, nil, nil)
err = readElement(r, &txin)
if err != nil {
return err

@ -314,7 +314,7 @@ func SendCoins(s uspv.SPVCon, adr btcutil.Address, sendAmt int64) error {
return err
}
// make new input from this utxo
thisInput := wire.NewTxIn(&utxo.Op, prevPKscript)
thisInput := wire.NewTxIn(&utxo.Op, prevPKscript, nil)
tx.AddTxIn(thisInput)
nokori -= utxo.Value
if nokori < -10000 { // minimum overage / fee is 1K now

@ -9,41 +9,128 @@ import (
"github.com/btcsuite/btcd/wire"
)
// BlockRootOK checks that all the txs in the block match the merkle root.
// Only checks merkle root; it doesn't look at txs themselves.
func BlockRootOK(blk wire.MsgBlock) bool {
var shas []*wire.ShaHash
for _, tx := range blk.Transactions { // make slice of txids
nSha := tx.TxSha()
shas = append(shas, &nSha)
var (
WitMagicBytes = []byte{0x6a, 0x24, 0xaa, 0x21, 0xa9, 0xed}
)
// BlockRootOK checks for block self-consistency.
// If the block has no wintess txs, and no coinbase witness commitment,
// it only checks the tx merkle root. If either a witness commitment or
// any witnesses are detected, it also checks that as well.
// Returns false if anything goes wrong, true if everything is fine.
func BlockOK(blk wire.MsgBlock) bool {
var txids, wtxids []*wire.ShaHash // txids and wtxids
// witMode true if any tx has a wintess OR coinbase has wit commit
var witMode bool
for _, tx := range blk.Transactions { // make slice of (w)/txids
txid := tx.TxSha()
wtxid := tx.WTxSha()
if !witMode && !txid.IsEqual(&wtxid) {
witMode = true
}
txids = append(txids, &txid)
wtxids = append(wtxids, &wtxid)
}
neededLen := int(nextPowerOfTwo(uint32(len(shas)))) // kindof ugly
for len(shas) < neededLen {
shas = append(shas, nil) // pad out tx slice to get the full tree base
var commitBytes []byte
// try to extract coinbase witness commitment (even if !witMode)
cb := blk.Transactions[0] // get coinbase tx
for i := len(cb.TxOut) - 1; i >= 0; i-- { // start at the last txout
if bytes.HasPrefix(cb.TxOut[i].PkScript, WitMagicBytes) &&
len(cb.TxOut[i].PkScript) > 37 {
// 38 bytes or more, and starts with WitMagicBytes is a hit
commitBytes = cb.TxOut[i].PkScript[6:38]
witMode = true // it there is a wit commit it must be valid
}
}
for len(shas) > 1 { // calculate merkle root. Terse, eh?
shas = append(shas[2:], MakeMerkleParent(shas[0], shas[1]))
} // auto recognizes coinbase-only blocks
fmt.Printf("MRs calcd %s given %s\n",
shas[0].String(), blk.Header.MerkleRoot.String())
return blk.Header.MerkleRoot.IsEqual(shas[0])
if witMode { // witmode, so check witness tree
// first find ways witMode can be disqualified
if len(commitBytes) != 32 {
// witness in block but didn't find a wintess commitment; fail
log.Printf("block %s has witness but no witcommit",
blk.BlockSha().String())
return false
}
if len(cb.TxIn) != 1 {
log.Printf("block %s coinbase tx has %d txins (must be 1)",
blk.BlockSha().String(), len(cb.TxIn))
return false
}
if len(cb.TxIn[0].Witness) != 1 {
log.Printf("block %s coinbase has %d witnesses (must be 1)",
blk.BlockSha().String(), len(cb.TxIn[0].Witness))
return false
}
if len(cb.TxIn[0].Witness[0]) != 32 {
log.Printf("block %s coinbase has %d byte witness nonce (not 32)",
blk.BlockSha().String(), len(cb.TxIn[0].Witness[0]))
return false
}
// witness nonce is the cb's witness, subject to above constraints
witNonce, err := wire.NewShaHash(cb.TxIn[0].Witness[0])
if err != nil {
log.Printf("Witness nonce error: %s", err.Error())
return false // not sure why that'd happen but fail
}
var empty [32]byte
wtxids[0].SetBytes(empty[:]) // coinbase wtxid is 0x00...00
// witness root calculated from wtixds
witRoot := calcRoot(wtxids)
calcWitCommit := wire.DoubleSha256SH(
append(witRoot.Bytes(), witNonce.Bytes()...))
// witness root given in coinbase op_return
givenWitCommit, err := wire.NewShaHash(commitBytes)
if err != nil {
log.Printf("Witness root error: %s", err.Error())
return false // not sure why that'd happen but fail
}
// they should be the same. If not, fail.
if !calcWitCommit.IsEqual(givenWitCommit) {
log.Printf("Block %s witRoot error: calc %s given %s",
blk.BlockSha().String(),
calcWitCommit.String(), givenWitCommit.String())
return false
}
}
// got through witMode check so that should be OK;
// check regular txid merkleroot. Which is, like, trivial.
return blk.Header.MerkleRoot.IsEqual(calcRoot(txids))
}
// calcRoot calculates the merkle root of a slice of hashes.
func calcRoot(hashes []*wire.ShaHash) *wire.ShaHash {
for len(hashes) < int(nextPowerOfTwo(uint32(len(hashes)))) {
hashes = append(hashes, nil) // pad out hash slice to get the full base
}
for len(hashes) > 1 { // calculate merkle root. Terse, eh?
hashes = append(hashes[2:], MakeMerkleParent(hashes[0], hashes[1]))
}
return hashes[0]
}
// IngestBlock is like IngestMerkleBlock but aralphic
// different enough that it's better to have 2 separate functions
func (s *SPVCon) IngestBlock(m *wire.MsgBlock) {
var err error
var buf bytes.Buffer
m.SerializeWitness(&buf)
fmt.Printf("block hex %x\n", buf.Bytes())
for i, tx := range m.Transactions {
// var buf bytes.Buffer
// m.SerializeWitness(&buf)
// fmt.Printf("block hex %x\n", buf.Bytes())
for _, tx := range m.Transactions {
// if i > 0 {
fmt.Printf("wtxid: %s\n", tx.WTxSha())
fmt.Printf(" txid: %s\n", tx.TxSha())
fmt.Printf("%d %s", i, TxToString(tx))
// fmt.Printf("%d %s", i, TxToString(tx))
// }
}
ok := BlockRootOK(*m) // check block self-consistency
ok := BlockOK(*m) // check block self-consistency
if !ok {
fmt.Printf("block %s not OK!!11\n", m.BlockSha().String())
return
@ -71,6 +158,7 @@ func (s *SPVCon) IngestBlock(m *wire.MsgBlock) {
wg.Add(len(m.Transactions))
for i, tx := range m.Transactions {
go func() {
defer wg.Done()
hits, err := s.TS.Ingest(tx, hah.height)
if err != nil {
log.Printf("Incoming Tx error: %s\n", err.Error())
@ -80,7 +168,6 @@ func (s *SPVCon) IngestBlock(m *wire.MsgBlock) {
log.Printf("block %d tx %d %s ingested and matches %d utxo/adrs.",
hah.height, i, tx.TxSha().String(), hits)
}
wg.Done()
}()
}
wg.Wait()

@ -88,10 +88,19 @@ func (s *SPVCon) fPositiveHandler() {
// send filter
s.SendFilter(filt)
fmt.Printf("sent filter %x\n", filt.MsgFilterLoad().Filter)
// clear the channel
for len(s.fPositives) != 0 {
fpAccumulator += <-s.fPositives
finClear:
for {
select {
case x := <-s.fPositives:
fpAccumulator += x
default:
break finClear
}
}
fmt.Printf("reset %d false positives\n", fpAccumulator)
// reset accumulator
fpAccumulator = 0

@ -139,6 +139,10 @@ func TxToString(tx *wire.MsgTx) string {
for i, in := range tx.TxIn {
str += fmt.Sprintf("Input %d: %s\n", i, in.PreviousOutPoint.String())
str += fmt.Sprintf("SigScript for input %d: %x\n", i, in.SignatureScript)
for j, wit := range in.Witness {
str += fmt.Sprintf("witness %d: %x\t", j, wit)
}
str += fmt.Sprintf("\n")
}
for i, out := range tx.TxOut {
if out != nil {
@ -148,12 +152,6 @@ func TxToString(tx *wire.MsgTx) string {
str += fmt.Sprintf("output %d nil (WARNING)\n", i)
}
}
for i, wit := range tx.TxWitness {
if wit != nil {
str += fmt.Sprintf("Witness %d: %x\n", i, wit.ScriptWitness)
}
}
return str
}