Пример #1
0
// TicketDbThumbprint takes all the tickets in the respective ticket db,
// sorts them, hashes their contents into a list, and then hashes that list.
// The resultant hash is the thumbprint of the ticket database, and should
// be the same across all clients that are synced to the same block. Returns
// an array of hashes len 3, containing (1) live tickets (2) spent tickets
// and (3) missed tickets.
// Do NOT use on mainnet or in production. For debug use only! Make sure
// the blockchain is frozen when you call this function.
func TicketDbThumbprint(tmdb *stake.TicketDB, chainParams *chaincfg.Params) ([]*chainhash.Hash, error) {
	// Container for the three master hashes to go into.
	dbThumbprints := make([]*chainhash.Hash, 3, 3)

	// (1) Live tickets.
	allLiveTickets := stake.NewTicketDataSliceEmpty()
	for i := 0; i < stake.BucketsSize; i++ {
		bucketTickets, err := tmdb.DumpLiveTickets(uint8(i))
		if err != nil {
			return nil, err
		}

		for _, td := range bucketTickets {
			allLiveTickets = append(allLiveTickets, td)
		}
	}

	// Sort by the number data hash, since we already have this implemented
	// and it's also unique.
	sort.Sort(allLiveTickets)

	// Create a buffer, dump all the data into it, and hash.
	var buf bytes.Buffer
	for _, td := range allLiveTickets {
		writeTicketDataToBuf(&buf, td)
	}

	liveHash := chainhash.HashFunc(buf.Bytes())
	liveThumbprint, err := chainhash.NewHash(liveHash[:])
	if err != nil {
		return nil, err
	}
	dbThumbprints[0] = liveThumbprint

	// (2) Spent tickets.
	height := tmdb.GetTopBlock()

	allSpentTickets := stake.NewTicketDataSliceEmpty()
	for i := int64(chainParams.StakeEnabledHeight); i <= height; i++ {
		bucketTickets, err := tmdb.DumpSpentTickets(i)
		if err != nil {
			return nil, err
		}

		for _, td := range bucketTickets {
			allSpentTickets = append(allSpentTickets, td)
		}
	}

	sort.Sort(allSpentTickets)

	buf.Reset() // Flush buffer
	for _, td := range allSpentTickets {
		writeTicketDataToBuf(&buf, td)
	}

	spentHash := chainhash.HashFunc(buf.Bytes())
	spentThumbprint, err := chainhash.NewHash(spentHash[:])
	if err != nil {
		return nil, err
	}
	dbThumbprints[1] = spentThumbprint

	// (3) Missed tickets.
	allMissedTickets := stake.NewTicketDataSliceEmpty()
	missedTickets, err := tmdb.DumpMissedTickets()
	if err != nil {
		return nil, err
	}

	for _, td := range missedTickets {
		allMissedTickets = append(allMissedTickets, td)
	}

	sort.Sort(allMissedTickets)

	buf.Reset() // Flush buffer
	missedHash := chainhash.HashFunc(buf.Bytes())
	missedThumbprint, err := chainhash.NewHash(missedHash[:])
	if err != nil {
		return nil, err
	}
	dbThumbprints[2] = missedThumbprint

	return dbThumbprints, nil
}
Пример #2
0
func (s *Store) debugBucketUnspentString(ns walletdb.ReadBucket,
	inclUnmined bool) (string, error) {
	var unspent []*unspentDebugData

	var op wire.OutPoint
	var block Block
	err := ns.NestedReadBucket(bucketUnspent).ForEach(func(k, v []byte) error {
		err := readCanonicalOutPoint(k, &op)
		if err != nil {
			return err
		}
		existsUnmined := false
		if existsRawUnminedInput(ns, k) != nil {
			// Skip including unmined if specified.
			if !inclUnmined {
				return nil
			}
			existsUnmined = true
		}
		err = readUnspentBlock(v, &block)
		if err != nil {
			return err
		}

		thisUnspentOutput := &unspentDebugData{
			op,
			existsUnmined,
			block.Hash,
			block.Height,
		}

		unspent = append(unspent, thisUnspentOutput)
		return nil
	})
	if err != nil {
		if _, ok := err.(Error); ok {
			return "", err
		}
		str := "failed iterating unspent bucket"
		return "", storeError(ErrDatabase, str, err)
	}

	sort.Sort(ByOutpoint(unspent))

	var buffer bytes.Buffer
	str := fmt.Sprintf("Unspent outputs\n\n")
	buffer.WriteString(str)

	// Create a buffer, dump all the data into it, and hash.
	var thumbprintBuf bytes.Buffer
	for _, udd := range unspent {
		str = fmt.Sprintf("Hash: %v, Index: %v, Tree: %v, Unmined: %v, "+
			"Block: %v, Block height: %v\n",
			udd.outPoint.Hash,
			udd.outPoint.Index,
			udd.outPoint.Tree,
			udd.unmined,
			udd.block,
			udd.blockHeight)
		buffer.WriteString(str)
		writeUnspentDebugDataToBuf(&thumbprintBuf, udd)
	}

	unspentHash := chainhash.HashFunc(thumbprintBuf.Bytes())
	unspentThumbprint, err := chainhash.NewHash(unspentHash[:])
	if err != nil {
		return "", err
	}

	str = fmt.Sprintf("\nUnspent outputs thumbprint: %v",
		unspentThumbprint)
	buffer.WriteString(str)

	return buffer.String(), nil
}