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 return nil, err
} }
_, multiSigIndex := findScriptOutputIndex(state.FundingTx, fundingPkScript) _, 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 lc.fundingP2SH = fundingPkScript
return lc, nil return lc, nil

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

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

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

@ -9,41 +9,128 @@ import (
"github.com/btcsuite/btcd/wire" "github.com/btcsuite/btcd/wire"
) )
// BlockRootOK checks that all the txs in the block match the merkle root. var (
// Only checks merkle root; it doesn't look at txs themselves. WitMagicBytes = []byte{0x6a, 0x24, 0xaa, 0x21, 0xa9, 0xed}
func BlockRootOK(blk wire.MsgBlock) bool { )
var shas []*wire.ShaHash
for _, tx := range blk.Transactions { // make slice of txids // BlockRootOK checks for block self-consistency.
nSha := tx.TxSha() // If the block has no wintess txs, and no coinbase witness commitment,
shas = append(shas, &nSha) // 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 { var commitBytes []byte
shas = append(shas, nil) // pad out tx slice to get the full tree base // 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])) if witMode { // witmode, so check witness tree
} // auto recognizes coinbase-only blocks // first find ways witMode can be disqualified
fmt.Printf("MRs calcd %s given %s\n", if len(commitBytes) != 32 {
shas[0].String(), blk.Header.MerkleRoot.String()) // witness in block but didn't find a wintess commitment; fail
return blk.Header.MerkleRoot.IsEqual(shas[0]) 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 // IngestBlock is like IngestMerkleBlock but aralphic
// different enough that it's better to have 2 separate functions // different enough that it's better to have 2 separate functions
func (s *SPVCon) IngestBlock(m *wire.MsgBlock) { func (s *SPVCon) IngestBlock(m *wire.MsgBlock) {
var err error var err error
var buf bytes.Buffer // var buf bytes.Buffer
m.SerializeWitness(&buf) // m.SerializeWitness(&buf)
fmt.Printf("block hex %x\n", buf.Bytes()) // fmt.Printf("block hex %x\n", buf.Bytes())
for i, tx := range m.Transactions { for _, tx := range m.Transactions {
// if i > 0 { // if i > 0 {
fmt.Printf("wtxid: %s\n", tx.WTxSha()) fmt.Printf("wtxid: %s\n", tx.WTxSha())
fmt.Printf(" txid: %s\n", tx.TxSha()) 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 { if !ok {
fmt.Printf("block %s not OK!!11\n", m.BlockSha().String()) fmt.Printf("block %s not OK!!11\n", m.BlockSha().String())
return return
@ -71,6 +158,7 @@ func (s *SPVCon) IngestBlock(m *wire.MsgBlock) {
wg.Add(len(m.Transactions)) wg.Add(len(m.Transactions))
for i, tx := range m.Transactions { for i, tx := range m.Transactions {
go func() { go func() {
defer wg.Done()
hits, err := s.TS.Ingest(tx, hah.height) hits, err := s.TS.Ingest(tx, hah.height)
if err != nil { if err != nil {
log.Printf("Incoming Tx error: %s\n", err.Error()) 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.", log.Printf("block %d tx %d %s ingested and matches %d utxo/adrs.",
hah.height, i, tx.TxSha().String(), hits) hah.height, i, tx.TxSha().String(), hits)
} }
wg.Done()
}() }()
} }
wg.Wait() wg.Wait()

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

@ -139,6 +139,10 @@ func TxToString(tx *wire.MsgTx) string {
for i, in := range tx.TxIn { for i, in := range tx.TxIn {
str += fmt.Sprintf("Input %d: %s\n", i, in.PreviousOutPoint.String()) str += fmt.Sprintf("Input %d: %s\n", i, in.PreviousOutPoint.String())
str += fmt.Sprintf("SigScript for input %d: %x\n", i, in.SignatureScript) 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 { for i, out := range tx.TxOut {
if out != nil { if out != nil {
@ -148,12 +152,6 @@ func TxToString(tx *wire.MsgTx) string {
str += fmt.Sprintf("output %d nil (WARNING)\n", i) 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 return str
} }