// TestElkremLess tries 10K hashes func TestElkremLess(t *testing.T) { var rcv ElkremReceiver sndr := NewElkremSender(wire.DoubleSha256SH([]byte("elktest2"))) for n := uint64(0); n < 5000; n++ { sha, err := sndr.AtIndex(n) if err != nil { t.Fatal(err) } if err = rcv.AddNext(sha); err != nil { t.Fatal(err) } } for n := uint64(0); n < 5000; n += 500 { if _, err := rcv.AtIndex(n); err != nil { t.Fatal(err) } } }
func MakeMerkleParent(left *wire.ShaHash, right *wire.ShaHash) *wire.ShaHash { // dupes can screw things up; CVE-2012-2459. check for them if left != nil && right != nil && left.IsEqual(right) { fmt.Printf("DUP HASH CRASH") return nil } // if left child is nil, output nil. Need this for hard mode. if left == nil { return nil } // if right is nil, hash left with itself if right == nil { right = left } // Concatenate the left and right nodes var sha [64]byte copy(sha[:32], left[:]) copy(sha[32:], right[:]) newSha := wire.DoubleSha256SH(sha[:]) return &newSha }
// 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.WitnessHash() if !witMode && !txid.IsEqual(&wtxid) { witMode = true } txids = append(txids, &txid) wtxids = append(wtxids, &wtxid) } 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 } } 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)) }
func RightSha(in wire.ShaHash) wire.ShaHash { return wire.DoubleSha256SH(append(in.Bytes(), 0x01)) // sha(sha(in, 1)) }
func LeftSha(in wire.ShaHash) wire.ShaHash { return wire.DoubleSha256SH(in.Bytes()) // left is sha(sha(in)) }