Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

consensus: Utxoview based script validation #135

Merged
merged 7 commits into from
Jun 14, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions csn/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,11 @@ func putBlockInPollard(
// thing first. (Especially since that thing isn't committed to in the
// PoW, but the signatures are...

if !ub.CheckBlock(outskip) {
return fmt.Errorf("height %d hash %s block invalid",
ub.Height, ub.Block.BlockHash().String())
}

// sort before ingestion; verify up above unsorts...
ub.ExtraData.AccProof.SortTargets()
// Fills in the empty(nil) nieces for verification && deletion
Expand Down
97 changes: 97 additions & 0 deletions util/udata.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@ package util

import (
"fmt"

"github.com/btcsuite/btcd/blockchain"
"github.com/btcsuite/btcd/chaincfg"
"github.com/btcsuite/btcd/txscript"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The extra empty lines in imports shouldn't be there

"github.com/btcsuite/btcd/wire"
"github.com/btcsuite/btcutil"
)

// ProofsProveBlock checks the consistency of a UBlock. Does the proof prove
Expand Down Expand Up @@ -72,3 +78,94 @@ func (ud *UData) Verify(nl uint64, h uint8) bool {
ud.AccProof.Targets = presort
return true
}

// ToUtxoView converts a UData into a btcd blockchain.UtxoViewpoint
// all the data is there, just a bit different format.
// Note that this needs blockchain.NewUtxoEntry() in btcd
func (ud *UData) ToUtxoView() *blockchain.UtxoViewpoint {
v := blockchain.NewUtxoViewpoint()
m := v.Entries()
// loop through leafDatas and convert them into UtxoEntries (pretty much the
// same thing
for _, ld := range ud.UtxoData {
txo := wire.NewTxOut(ld.Amt, ld.PkScript)
utxo := blockchain.NewUtxoEntry(txo, ld.Height, ld.Coinbase)
m[ld.Outpoint] = utxo
}

return v
}

/*
blockchain.NewUtxoEntry() looks like this:
// NewUtxoEntry returns a new UtxoEntry built from the arguments.
func NewUtxoEntry(
txOut *wire.TxOut, blockHeight int32, isCoinbase bool) *UtxoEntry {
var cbFlag txoFlags
if isCoinbase {
cbFlag |= tfCoinBase
}

return &UtxoEntry{
amount: txOut.Value,
pkScript: txOut.PkScript,
blockHeight: blockHeight,
packedFlags: cbFlag,
}
}
*/

// CheckBlock does all internal block checks for a UBlock
// right now checks the signatures
func (ub *UBlock) CheckBlock(outskip []uint32) bool {

view := ub.ExtraData.ToUtxoView()
viewMap := view.Entries()
var txonum uint32

sigCache := txscript.NewSigCache(8192)
hashCache := txscript.NewHashCache(8192)

for txnum, tx := range ub.Block.Transactions {
outputsInTx := uint32(len(tx.TxOut))
if txnum == 0 {
txonum += outputsInTx
continue // skip checks for coinbase TX for now. Or maybe it'll work?
}

utilTx := btcutil.NewTx(tx)
// hardcoded testnet3 for now
_, err := blockchain.CheckTransactionInputs(
utilTx, ub.Height, view, &chaincfg.TestNet3Params)
if err != nil {
fmt.Printf("Tx %s fails CheckTransactionInputs: %s\n",
utilTx.Hash().String(), err.Error())
return false
}

// no scriptflags for now
err = blockchain.ValidateTransactionScripts(
utilTx, view, 0, sigCache, hashCache)
if err != nil {
fmt.Printf("Tx %s fails ValidateTransactionScripts: %s\n",
utilTx.Hash().String(), err.Error())
return false
}

// add txos to the UtxoView if they're also consumed in this block
// (will be on the output skiplist from DedupeBlock)
// The order we do this in should ensure that a incorrectly ordered
// sequence (tx 5 spending tx 8) will fail here.
for len(outskip) > 0 && outskip[0] < txonum+outputsInTx {
idx := outskip[0] - txonum
skipTxo := wire.NewTxOut(tx.TxOut[idx].Value, tx.TxOut[idx].PkScript)
skippedEntry := blockchain.NewUtxoEntry(skipTxo, ub.Height, false)
skippedOutpoint := wire.OutPoint{Hash: tx.TxHash(), Index: idx}
viewMap[skippedOutpoint] = skippedEntry
outskip = outskip[1:] // pop off from output skiplist
}
txonum += outputsInTx
}

return true
}
2 changes: 1 addition & 1 deletion util/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ func GetUDataFromFile(tipnum int32) (ud UData, err error) {

// BlockToAdds turns all the new utxos in a msgblock into leafTxos
// uses remember slice up to number of txos, but doesn't check that it's the
// right lenght. Similar with skiplist, doesn't check it.
// right length. Similar with skiplist, doesn't check it.
func BlockToAddLeaves(blk wire.MsgBlock,
remember []bool, skiplist []uint32,
height int32) (leaves []accumulator.Leaf) {
Expand Down