本文整理汇总了Golang中github.com/decred/dcrd/blockchain/stake.IsSSGen函数的典型用法代码示例。如果您正苦于以下问题:Golang IsSSGen函数的具体用法?Golang IsSSGen怎么用?Golang IsSSGen使用的例子?那么恭喜您, 这里精选的函数代码示例或许可以为您提供帮助。
在下文中一共展示了IsSSGen函数的15个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的Golang代码示例。
示例1: AddUnconfirmedTx
// AddUnconfirmedTx adds all addresses related to the transaction to the
// unconfirmed (memory-only) address index.
//
// NOTE: This transaction MUST have already been validated by the memory pool
// before calling this function with it and have all of the inputs available in
// the provided utxo view. Failure to do so could result in some or all
// addresses not being indexed.
//
// This function is safe for concurrent access.
func (idx *AddrIndex) AddUnconfirmedTx(tx *dcrutil.Tx, utxoView *blockchain.UtxoViewpoint) {
// Index addresses of all referenced previous transaction outputs.
//
// The existence checks are elided since this is only called after the
// transaction has already been validated and thus all inputs are
// already known to exist.
msgTx := tx.MsgTx()
isSSGen, _ := stake.IsSSGen(msgTx)
for i, txIn := range msgTx.TxIn {
// Skip stakebase.
if i == 0 && isSSGen {
continue
}
entry := utxoView.LookupEntry(&txIn.PreviousOutPoint.Hash)
if entry == nil {
// Ignore missing entries. This should never happen
// in practice since the function comments specifically
// call out all inputs must be available.
continue
}
version := entry.ScriptVersionByIndex(txIn.PreviousOutPoint.Index)
pkScript := entry.PkScriptByIndex(txIn.PreviousOutPoint.Index)
txType := entry.TransactionType()
idx.indexUnconfirmedAddresses(version, pkScript, tx,
txType == stake.TxTypeSStx)
}
// Index addresses of all created outputs.
isSStx, _ := stake.IsSStx(msgTx)
for _, txOut := range msgTx.TxOut {
idx.indexUnconfirmedAddresses(txOut.Version, txOut.PkScript, tx,
isSStx)
}
}
示例2: FetchTransactionStore
// FetchTransactionStore fetches the input transactions referenced by the
// passed transaction from the point of view of the end of the main chain. It
// also attempts to fetch the transaction itself so the returned TxStore can be
// examined for duplicate transactions.
// IsValid indicates if the current block on head has had its TxTreeRegular
// validated by the stake voters.
func (b *BlockChain) FetchTransactionStore(tx *dcrutil.Tx,
isValid bool) (TxStore, error) {
isSSGen, _ := stake.IsSSGen(tx)
// Create a set of needed transactions from the transactions referenced
// by the inputs of the passed transaction. Also, add the passed
// transaction itself as a way for the caller to detect duplicates.
txNeededSet := make(map[chainhash.Hash]struct{})
txNeededSet[*tx.Sha()] = struct{}{}
for i, txIn := range tx.MsgTx().TxIn {
// Skip all stakebase inputs.
if isSSGen && (i == 0) {
continue
}
txNeededSet[txIn.PreviousOutPoint.Hash] = struct{}{}
}
// Request the input transactions from the point of view of the end of
// the main chain without including fully spent transactions in the
// results. Fully spent transactions are only needed for chain
// reorganization which does not apply here.
txStore := fetchTxStoreMain(b.db, txNeededSet, false)
topBlock, err := b.getBlockFromHash(b.bestChain.hash)
if err != nil {
return nil, err
}
if isValid {
connectTxTree(txStore, topBlock, true)
}
return txStore, nil
}
示例3: voteVersionsInBlock
// voteVersionsInBlock returns all versions in a block.
func voteVersionsInBlock(bl *dcrutil.Block, params *chaincfg.Params) []uint32 {
versions := make([]uint32, 0, params.TicketsPerBlock)
for _, stx := range bl.MsgBlock().STransactions {
if is, _ := stake.IsSSGen(stx); !is {
continue
}
versions = append(versions, stake.SSGenVersion(stx))
}
return versions
}
示例4: FetchUtxoView
// FetchUtxoView loads utxo details about the input transactions referenced by
// the passed transaction from the point of view of the end of the main chain.
// It also attempts to fetch the utxo details for the transaction itself so the
// returned view can be examined for duplicate unspent transaction outputs.
//
// This function is safe for concurrent access however the returned view is NOT.
func (b *BlockChain) FetchUtxoView(tx *dcrutil.Tx, treeValid bool) (*UtxoViewpoint,
error) {
b.chainLock.RLock()
defer b.chainLock.RUnlock()
// Request the utxos from the point of view of the end of the main
// chain.
view := NewUtxoViewpoint()
if treeValid {
view.SetStakeViewpoint(ViewpointPrevValidRegular)
block, err := b.fetchBlockFromHash(&b.bestNode.hash)
if err != nil {
return nil, err
}
parent, err := b.fetchBlockFromHash(&b.bestNode.header.PrevBlock)
if err != nil {
return nil, err
}
err = view.fetchInputUtxos(b.db, block, parent)
if err != nil {
return nil, err
}
for i, blockTx := range block.Transactions() {
err := view.connectTransaction(blockTx, b.bestNode.height,
uint32(i), nil)
if err != nil {
return nil, err
}
}
}
view.SetBestHash(&b.bestNode.hash)
// Create a set of needed transactions based on those referenced by the
// inputs of the passed transaction. Also, add the passed transaction
// itself as a way for the caller to detect duplicates that are not
// fully spent.
txNeededSet := make(map[chainhash.Hash]struct{})
txNeededSet[*tx.Sha()] = struct{}{}
msgTx := tx.MsgTx()
isSSGen, _ := stake.IsSSGen(msgTx)
if !IsCoinBaseTx(msgTx) {
for i, txIn := range msgTx.TxIn {
if isSSGen && i == 0 {
continue
}
txNeededSet[txIn.PreviousOutPoint.Hash] = struct{}{}
}
}
err := view.fetchUtxosMain(b.db, txNeededSet)
return view, err
}
示例5: CalculateAddedSubsidy
// CalculateAddedSubsidy calculates the amount of subsidy added by a block
// and its parent. The blocks passed to this function MUST be valid blocks
// that have already been confirmed to abide by the consensus rules of the
// network, or the function might panic.
func CalculateAddedSubsidy(block, parent *dcrutil.Block) int64 {
var subsidy int64
regularTxTreeValid := dcrutil.IsFlagSet16(block.MsgBlock().Header.VoteBits,
dcrutil.BlockValid)
if regularTxTreeValid {
subsidy += parent.MsgBlock().Transactions[0].TxIn[0].ValueIn
}
for _, stx := range block.MsgBlock().STransactions {
if isSSGen, _ := stake.IsSSGen(stx); isSSGen {
subsidy += stx.TxIn[0].ValueIn
}
}
return subsidy
}
示例6: makeUtxoView
// makeUtxoView creates a mock unspent transaction output view by using the
// transaction index in order to look up all inputs referenced by the
// transactions in the block. This is sometimes needed when catching indexes up
// because many of the txouts could actually already be spent however the
// associated scripts are still required to index them.
func makeUtxoView(dbTx database.Tx, block, parent *dcrutil.Block) (*blockchain.UtxoViewpoint, error) {
view := blockchain.NewUtxoViewpoint()
regularTxTreeValid := dcrutil.IsFlagSet16(block.MsgBlock().Header.VoteBits,
dcrutil.BlockValid)
if regularTxTreeValid {
for txIdx, tx := range parent.Transactions() {
// Coinbases do not reference any inputs. Since the block is
// required to have already gone through full validation, it has
// already been proven on the first transaction in the block is
// a coinbase.
if txIdx == 0 {
continue
}
// Use the transaction index to load all of the referenced
// inputs and add their outputs to the view.
for _, txIn := range tx.MsgTx().TxIn {
// Skip already fetched outputs.
originOut := &txIn.PreviousOutPoint
if view.LookupEntry(&originOut.Hash) != nil {
continue
}
originTx, err := dbFetchTx(dbTx, originOut.Hash)
if err != nil {
return nil, err
}
view.AddTxOuts(dcrutil.NewTx(originTx),
int64(wire.NullBlockHeight), wire.NullBlockIndex)
}
}
}
for _, tx := range block.STransactions() {
msgTx := tx.MsgTx()
isSSGen, _ := stake.IsSSGen(msgTx)
// Use the transaction index to load all of the referenced
// inputs and add their outputs to the view.
for i, txIn := range msgTx.TxIn {
// Skip stakebases.
if isSSGen && i == 0 {
continue
}
originOut := &txIn.PreviousOutPoint
if view.LookupEntry(&originOut.Hash) != nil {
continue
}
originTx, err := dbFetchTx(dbTx, originOut.Hash)
if err != nil {
return nil, err
}
view.AddTxOuts(dcrutil.NewTx(originTx), int64(wire.NullBlockHeight),
wire.NullBlockIndex)
}
}
return view, nil
}
示例7: DebugMsgTxString
// DebugMsgTxString dumps a verbose message containing information about the
// contents of a transaction.
func DebugMsgTxString(msgTx *wire.MsgTx) string {
tx := dcrutil.NewTx(msgTx)
isSStx, _ := stake.IsSStx(tx)
isSSGen, _ := stake.IsSSGen(tx)
var sstxType []bool
var sstxPkhs [][]byte
var sstxAmts []int64
var sstxRules [][]bool
var sstxLimits [][]uint16
if isSStx {
sstxType, sstxPkhs, sstxAmts, _, sstxRules, sstxLimits =
stake.GetSStxStakeOutputInfo(tx)
}
var buffer bytes.Buffer
hash := msgTx.TxSha()
str := fmt.Sprintf("Transaction hash: %v, Version %v, Locktime: %v, "+
"Expiry %v\n\n", hash, msgTx.Version, msgTx.LockTime, msgTx.Expiry)
buffer.WriteString(str)
str = fmt.Sprintf("==INPUTS==\nNumber of inputs: %v\n\n",
len(msgTx.TxIn))
buffer.WriteString(str)
for i, input := range msgTx.TxIn {
str = fmt.Sprintf("Input number: %v\n", i)
buffer.WriteString(str)
str = fmt.Sprintf("Previous outpoint hash: %v, ",
input.PreviousOutPoint.Hash)
buffer.WriteString(str)
str = fmt.Sprintf("Previous outpoint index: %v, ",
input.PreviousOutPoint.Index)
buffer.WriteString(str)
str = fmt.Sprintf("Previous outpoint tree: %v \n",
input.PreviousOutPoint.Tree)
buffer.WriteString(str)
str = fmt.Sprintf("Sequence: %v \n",
input.Sequence)
buffer.WriteString(str)
str = fmt.Sprintf("ValueIn: %v \n",
input.ValueIn)
buffer.WriteString(str)
str = fmt.Sprintf("BlockHeight: %v \n",
input.BlockHeight)
buffer.WriteString(str)
str = fmt.Sprintf("BlockIndex: %v \n",
input.BlockIndex)
buffer.WriteString(str)
str = fmt.Sprintf("Raw signature script: %x \n", input.SignatureScript)
buffer.WriteString(str)
sigScr, _ := txscript.DisasmString(input.SignatureScript)
str = fmt.Sprintf("Disasmed signature script: %v \n\n",
sigScr)
buffer.WriteString(str)
}
str = fmt.Sprintf("==OUTPUTS==\nNumber of outputs: %v\n\n",
len(msgTx.TxOut))
buffer.WriteString(str)
for i, output := range msgTx.TxOut {
str = fmt.Sprintf("Output number: %v\n", i)
buffer.WriteString(str)
coins := float64(output.Value) / 1e8
str = fmt.Sprintf("Output amount: %v atoms or %v coins\n", output.Value,
coins)
buffer.WriteString(str)
// SStx OP_RETURNs, dump pkhs and amts committed
if isSStx && i != 0 && i%2 == 1 {
coins := float64(sstxAmts[i/2]) / 1e8
str = fmt.Sprintf("SStx commit amount: %v atoms or %v coins\n",
sstxAmts[i/2], coins)
buffer.WriteString(str)
str = fmt.Sprintf("SStx commit address: %x\n",
sstxPkhs[i/2])
buffer.WriteString(str)
str = fmt.Sprintf("SStx address type is P2SH: %v\n",
sstxType[i/2])
buffer.WriteString(str)
str = fmt.Sprintf("SStx all address types is P2SH: %v\n",
sstxType)
buffer.WriteString(str)
str = fmt.Sprintf("Voting is fee limited: %v\n",
//.........这里部分代码省略.........
示例8: fetchInputTransactions
//.........这里部分代码省略.........
}
}
// Request the input transactions from the point of view of the node.
txNeededStore, err := b.fetchTxStore(node, block, txNeededSet, viewpoint)
if err != nil {
return nil, err
}
// Merge the results of the requested transactions and the in-flight
// transactions.
for _, txD := range txNeededStore {
txStore[*txD.Hash] = txD
}
return txStore, nil
}
// Case 2+3: ViewpointPrevValidStake and ViewpointPrevValidStake.
// For ViewpointPrevValidStake, we need the viewpoint of the
// current chain with the TxTreeRegular of the previous block
// added so we can validate the TxTreeStake of the current block.
// For ViewpointPrevInvalidStake, we need the viewpoint of the
// current chain with the TxTreeRegular of the previous block
// missing so we can validate the TxTreeStake of the current block.
if viewpoint == ViewpointPrevValidStake ||
viewpoint == ViewpointPrevInvalidStake {
// We need all of the stake tx txins. None of these are considered
// in-flight in relation to the regular tx tree or to other tx in
// the stake tx tree, so don't do any of those expensive checks and
// just append it to the tx slice.
stransactions := block.STransactions()
for _, tx := range stransactions {
isSSGen, _ := stake.IsSSGen(tx)
for i, txIn := range tx.MsgTx().TxIn {
// Ignore stakebases.
if isSSGen && i == 0 {
continue
}
// Add an entry to the transaction store for the needed
// transaction with it set to missing by default.
originHash := &txIn.PreviousOutPoint.Hash
txD := &TxData{Hash: originHash, Err: database.ErrTxShaMissing}
txStore[*originHash] = txD
txNeededSet[*originHash] = struct{}{}
}
}
// Request the input transactions from the point of view of the node.
txNeededStore, err := b.fetchTxStore(node, block, txNeededSet, viewpoint)
if err != nil {
return nil, err
}
return txNeededStore, nil
}
// Case 4+5: ViewpointPrevValidRegular and
// ViewpointPrevInvalidRegular.
// For ViewpointPrevValidRegular, we need the viewpoint of the
// current chain with the TxTreeRegular of the previous block
// and the TxTreeStake of the current block added so we can
// validate the TxTreeRegular of the current block.
示例9: addRelevantTx
//.........这里部分代码省略.........
insert = true
break
}
// Log errors if there were any. At this point the ticket
// must be invalid, so insert it into the list of invalid
// user tickets.
if errEval != nil {
log.Warnf("Ticket %v failed ticket evaluation for "+
"the stake pool: %s", rec.Hash, err.Error())
}
errUpdate := w.StakeMgr.UpdateStakePoolUserInvalTickets(
stakemgrNs, addr, &rec.Hash)
if errUpdate != nil {
log.Warnf("Failed to update pool user %v with "+
"invalid ticket %v", addr.EncodeAddress(),
rec.Hash)
}
}
}
}
if insert {
err := w.StakeMgr.InsertSStx(stakemgrNs, tx, w.VoteBits)
if err != nil {
log.Errorf("Failed to insert SStx %v"+
"into the stake store.", tx.Sha())
}
}
}
// Handle incoming SSGen; store them if we own
// the ticket used to purchase them.
if is, _ := stake.IsSSGen(&rec.MsgTx); is {
if block != nil {
txInHash := tx.MsgTx().TxIn[1].PreviousOutPoint.Hash
if w.StakeMgr.CheckHashInStore(&txInHash) {
w.StakeMgr.InsertSSGen(stakemgrNs, &block.Hash,
int64(block.Height),
&txHash,
w.VoteBits.Bits,
&txInHash)
}
// If we're running as a stake pool, insert
// the stake pool user ticket update too.
if w.stakePoolEnabled {
txInHeight := tx.MsgTx().TxIn[1].BlockHeight
poolTicket := &wstakemgr.PoolTicket{
Ticket: txInHash,
HeightTicket: txInHeight,
Status: wstakemgr.TSVoted,
SpentBy: txHash,
HeightSpent: uint32(block.Height),
}
poolUser, err := w.StakeMgr.SStxAddress(stakemgrNs, &txInHash)
if err != nil {
log.Warnf("Failed to fetch stake pool user for "+
"ticket %v (voted ticket)", txInHash)
} else {
err = w.StakeMgr.UpdateStakePoolUserTickets(
stakemgrNs, addrmgrNs, poolUser, poolTicket)
if err != nil {
log.Warnf("Failed to update stake pool ticket for "+
"stake pool user %s after voting",
示例10: generateVote
//.........这里部分代码省略.........
// SStx tagged output as an OutPoint.
prevOut := wire.NewOutPoint(sstxHash,
0, // Index 0
1) // Tree stake
txIn := wire.NewTxIn(prevOut, []byte{})
msgTx.AddTxIn(txIn)
// 3. Add the OP_RETURN null data pushes of the block header hash,
// the block height, and votebits, then add all the OP_SSGEN tagged
// outputs.
//
// Block reference output.
blockRefScript, err := txscript.GenerateSSGenBlockRef(*blockHash,
uint32(height))
if err != nil {
return nil, err
}
blockRefOut := wire.NewTxOut(0, blockRefScript)
msgTx.AddTxOut(blockRefOut)
// Votebits output.
blockVBScript, err := generateVoteScript(voteBits)
if err != nil {
return nil, err
}
blockVBOut := wire.NewTxOut(0, blockVBScript)
msgTx.AddTxOut(blockVBOut)
// Add all the SSGen-tagged transaction outputs to the transaction after
// performing some validity checks.
for i, ssgenPkh := range ssgenPkhs {
// Create a new script which pays to the provided address specified in
// the original ticket tx.
var ssgenOutScript []byte
switch ssgenPayTypes[i] {
case false: // P2PKH
ssgenOutScript, err = txscript.PayToSSGenPKHDirect(ssgenPkh)
if err != nil {
return nil, err
}
case true: // P2SH
ssgenOutScript, err = txscript.PayToSSGenSHDirect(ssgenPkh)
if err != nil {
return nil, err
}
}
// Add the txout to our SSGen tx.
txOut := wire.NewTxOut(ssgenCalcAmts[i], ssgenOutScript)
msgTx.AddTxOut(txOut)
}
// Check to make sure our SSGen was created correctly.
_, err = stake.IsSSGen(msgTx)
if err != nil {
return nil, err
}
// Sign the transaction.
err = s.SignVRTransaction(waddrmgrNs, msgTx, sstx, true)
if err != nil {
return nil, err
}
// Store the information about the SSGen.
hash := msgTx.TxSha()
err = s.insertSSGen(ns,
blockHash,
height,
&hash,
voteBits.Bits,
sstx.Sha())
if err != nil {
return nil, err
}
// Send the transaction.
ssgenSha, err := s.chainSvr.SendRawTransaction(msgTx, allowHighFees)
if err != nil {
return nil, err
}
log.Debugf("Generated SSGen %v, voting on block %v at height %v. "+
"The ticket used to generate the SSGen was %v.",
ssgenSha, blockHash, height, sstxHash)
// Generate a notification to return.
ntfn := &StakeNotification{
TxType: int8(stake.TxTypeSSGen),
TxHash: *ssgenSha,
BlockHash: *blockHash,
Height: int32(height),
Amount: 0,
SStxIn: *sstx.Sha(),
VoteBits: voteBits.Bits,
}
return ntfn, nil
}
示例11: indexBlock
// indexBlock extract all of the standard addresses from all of the transactions
// in the passed block and maps each of them to the assocaited transaction using
// the passed map.
func (idx *AddrIndex) indexBlock(data writeIndexData, block, parent *dcrutil.Block, view *blockchain.UtxoViewpoint) {
regularTxTreeValid := dcrutil.IsFlagSet16(block.MsgBlock().Header.VoteBits,
dcrutil.BlockValid)
var stakeStartIdx int
if regularTxTreeValid {
for txIdx, tx := range parent.Transactions() {
// Coinbases do not reference any inputs. Since the block is
// required to have already gone through full validation, it has
// already been proven on the first transaction in the block is
// a coinbase.
if txIdx != 0 {
for _, txIn := range tx.MsgTx().TxIn {
// The view should always have the input since
// the index contract requires it, however, be
// safe and simply ignore any missing entries.
origin := &txIn.PreviousOutPoint
entry := view.LookupEntry(&origin.Hash)
if entry == nil {
log.Warnf("Missing input %v for tx %v while "+
"indexing block %v (height %v)\n", origin.Hash,
tx.Sha(), block.Sha(), block.Height())
continue
}
version := entry.ScriptVersionByIndex(origin.Index)
pkScript := entry.PkScriptByIndex(origin.Index)
txType := entry.TransactionType()
idx.indexPkScript(data, version, pkScript, txIdx,
txType == stake.TxTypeSStx)
}
}
for _, txOut := range tx.MsgTx().TxOut {
idx.indexPkScript(data, txOut.Version, txOut.PkScript, txIdx,
false)
}
}
stakeStartIdx = len(parent.Transactions())
}
for txIdx, tx := range block.STransactions() {
msgTx := tx.MsgTx()
thisTxOffset := txIdx + stakeStartIdx
isSSGen, _ := stake.IsSSGen(msgTx)
for i, txIn := range msgTx.TxIn {
// Skip stakebases.
if isSSGen && i == 0 {
continue
}
// The view should always have the input since
// the index contract requires it, however, be
// safe and simply ignore any missing entries.
origin := &txIn.PreviousOutPoint
entry := view.LookupEntry(&origin.Hash)
if entry == nil {
log.Warnf("Missing input %v for tx %v while "+
"indexing block %v (height %v)\n", origin.Hash,
tx.Sha(), block.Sha(), block.Height())
continue
}
version := entry.ScriptVersionByIndex(origin.Index)
pkScript := entry.PkScriptByIndex(origin.Index)
txType := entry.TransactionType()
idx.indexPkScript(data, version, pkScript, thisTxOffset,
txType == stake.TxTypeSStx)
}
isSStx, _ := stake.IsSStx(msgTx)
for _, txOut := range msgTx.TxOut {
idx.indexPkScript(data, txOut.Version, txOut.PkScript,
thisTxOffset, isSStx)
}
}
}
示例12: connectTickets
// connectTickets updates the passed map by removing removing any tickets
// from the ticket pool that have been considered spent or missed in this block
// according to the block header. Then, it connects all the newly mature tickets
// to the passed map.
func (b *BlockChain) connectTickets(tixStore TicketStore,
node *blockNode,
block *dcrutil.Block) error {
if tixStore == nil {
return fmt.Errorf("nil ticket store!")
}
// Nothing to do if tickets haven't yet possibly matured.
height := node.height
if height < b.chainParams.StakeEnabledHeight {
return nil
}
parentBlock, err := b.GetBlockFromHash(node.parentHash)
if err != nil {
return err
}
revocations := node.header.Revocations
tM := int64(b.chainParams.TicketMaturity)
// Skip a number of validation steps before we requiring chain
// voting.
if node.height >= b.chainParams.StakeValidationHeight {
regularTxTreeValid := dcrutil.IsFlagSet16(node.header.VoteBits,
dcrutil.BlockValid)
thisNodeStakeViewpoint := ViewpointPrevInvalidStake
if regularTxTreeValid {
thisNodeStakeViewpoint = ViewpointPrevValidStake
}
// We need the missed tickets bucket from the original perspective of
// the node.
missedTickets, err := b.GenerateMissedTickets(tixStore)
if err != nil {
return err
}
// TxStore at blockchain HEAD + TxTreeRegular of prevBlock (if
// validated) for this node.
txInputStoreStake, err := b.fetchInputTransactions(node, block,
thisNodeStakeViewpoint)
if err != nil {
errStr := fmt.Sprintf("fetchInputTransactions failed for incoming "+
"node %v; error given: %v", node.hash, err)
return errors.New(errStr)
}
// PART 1: Spend/miss winner tickets
// Iterate through all the SSGen (vote) tx in the block and add them to
// a map of tickets that were actually used.
spentTicketsFromBlock := make(map[chainhash.Hash]bool)
numberOfSSgen := 0
for _, staketx := range block.STransactions() {
if is, _ := stake.IsSSGen(staketx); is {
msgTx := staketx.MsgTx()
sstxIn := msgTx.TxIn[1] // sstx input
sstxHash := sstxIn.PreviousOutPoint.Hash
originTx, exists := txInputStoreStake[sstxHash]
if !exists {
str := fmt.Sprintf("unable to find input transaction "+
"%v for transaction %v", sstxHash, staketx.Sha())
return ruleError(ErrMissingTx, str)
}
sstxHeight := originTx.BlockHeight
// Check maturity of ticket; we can only spend the ticket after it
// hits maturity at height + tM + 1.
if (height - sstxHeight) < (tM + 1) {
blockSha := block.Sha()
errStr := fmt.Sprintf("Error: A ticket spend as an SSGen in "+
"block height %v was immature! Block sha %v",
height,
blockSha)
return errors.New(errStr)
}
// Fill out the ticket data.
spentTicketsFromBlock[sstxHash] = true
numberOfSSgen++
}
}
// Obtain the TicketsPerBlock many tickets that were selected this round,
// then check these against the tickets that were actually used to make
// sure that any SSGen actually match the selected tickets. Commit the
// spent or missed tickets to the ticket store after.
spentAndMissedTickets := make(TicketStore)
tixSpent := 0
tixMissed := 0
// Sort the entire list of tickets lexicographically by sorting
//.........这里部分代码省略.........
示例13: traceDevPremineOuts
// traceDevPremineOuts returns a list of outpoints that are part of the dev
// premine coins and are ancestors of the inputs to the passed transaction hash.
func traceDevPremineOuts(client *dcrrpcclient.Client, txHash *chainhash.Hash) ([]wire.OutPoint, error) {
// Trace the lineage of all inputs to the provided transaction back to
// the coinbase outputs that generated them and add those outpoints to
// a list. Also, keep track of all of the processed transactions in
// order to avoid processing duplicates.
knownCoinbases := make(map[chainhash.Hash]struct{})
processedHashes := make(map[chainhash.Hash]struct{})
coinbaseOuts := make([]wire.OutPoint, 0, 10)
processOuts := []wire.OutPoint{{Hash: *txHash}}
for len(processOuts) > 0 {
// Grab the first outpoint to process and skip it if it has
// already been traced.
outpoint := processOuts[0]
processOuts = processOuts[1:]
if _, exists := processedHashes[outpoint.Hash]; exists {
if _, exists := knownCoinbases[outpoint.Hash]; exists {
coinbaseOuts = append(coinbaseOuts, outpoint)
}
continue
}
processedHashes[outpoint.Hash] = struct{}{}
// Request the transaction for the outpoint from the server.
tx, err := client.GetRawTransaction(&outpoint.Hash)
if err != nil {
return nil, fmt.Errorf("failed to get transaction %v: %v",
&outpoint.Hash, err)
}
// Add the outpoint to the coinbase outputs list when it is part
// of a coinbase transaction. Also, keep track of the fact the
// transaction is a coinbase to use when avoiding duplicate
// checks.
if blockchain.IsCoinBase(tx) {
knownCoinbases[outpoint.Hash] = struct{}{}
coinbaseOuts = append(coinbaseOuts, outpoint)
continue
}
// Add the inputs to the transaction to the list of transactions
// to load and continue tracing.
//
// However, skip the first input to stake generation txns since
// they are creating new coins. The remaining inputs to a
// stake generation transaction still need to be traced since
// they represent the coins that purchased the ticket.
txIns := tx.MsgTx().TxIn
isSSGen, _ := stake.IsSSGen(tx.MsgTx())
if isSSGen {
txIns = txIns[1:]
}
for _, txIn := range txIns {
processOuts = append(processOuts, txIn.PreviousOutPoint)
}
}
// Add any of the outputs that are dev premine outputs to a list.
var devPremineOuts []wire.OutPoint
for _, coinbaseOut := range coinbaseOuts {
if isDevPremineOut(coinbaseOut) {
devPremineOuts = append(devPremineOuts, coinbaseOut)
}
}
return devPremineOuts, nil
}
示例14: maybeAcceptBlock
// maybeAcceptBlock potentially accepts a block into the memory block chain.
// It performs several validation checks which depend on its position within
// the block chain before adding it. The block is expected to have already gone
// through ProcessBlock before calling this function with it.
//
// The flags modify the behavior of this function as follows:
// - BFDryRun: The memory chain index will not be pruned and no accept
// notification will be sent since the block is not being accepted.
func (b *BlockChain) maybeAcceptBlock(block *dcrutil.Block,
flags BehaviorFlags) (bool, error) {
dryRun := flags&BFDryRun == BFDryRun
// Get a block node for the block previous to this one. Will be nil
// if this is the genesis block.
prevNode, err := b.getPrevNodeFromBlock(block)
if err != nil {
log.Debugf("getPrevNodeFromBlock: %v", err)
return false, err
}
// The height of this block is one more than the referenced previous
// block.
blockHeight := int64(0)
if prevNode != nil {
blockHeight = prevNode.height + 1
}
block.SetHeight(blockHeight)
// The block must pass all of the validation rules which depend on the
// position of the block within the block chain.
err = b.checkBlockContext(block, prevNode, flags)
if err != nil {
return false, err
}
// Prune block nodes which are no longer needed before creating
// a new node.
if !dryRun {
err = b.pruneBlockNodes()
if err != nil {
return false, err
}
}
// Create a new block node for the block and add it to the in-memory
// block chain (could be either a side chain or the main chain).
blockHeader := &block.MsgBlock().Header
var voteBitsStake []uint16
for _, stx := range block.STransactions() {
if is, _ := stake.IsSSGen(stx); is {
vb := stake.GetSSGenVoteBits(stx)
voteBitsStake = append(voteBitsStake, vb)
}
}
newNode := newBlockNode(blockHeader, block.Sha(), blockHeight, voteBitsStake)
if prevNode != nil {
newNode.parent = prevNode
newNode.height = blockHeight
newNode.workSum.Add(prevNode.workSum, newNode.workSum)
}
// Connect the passed block to the chain while respecting proper chain
// selection according to the chain with the most proof of work. This
// also handles validation of the transaction scripts.
var onMainChain bool
onMainChain, err = b.connectBestChain(newNode, block, flags)
if err != nil {
return false, err
}
// Notify the caller that the new block was accepted into the block
// chain. The caller would typically want to react by relaying the
// inventory to other peers.
if !dryRun {
b.sendNotification(NTBlockAccepted,
&BlockAcceptedNtfnsData{onMainChain, block})
}
return onMainChain, nil
}
示例15: fetchInputUtxos
// fetchInputUtxos loads utxo details about the input transactions referenced
// by the transactions in the given block into the view from the database as
// needed. In particular, referenced entries that are earlier in the block are
// added to the view and entries that are already in the view are not modified.
func (view *UtxoViewpoint) fetchInputUtxos(db database.DB,
block, parent *dcrutil.Block) error {
viewpoint := view.StakeViewpoint()
// Build a map of in-flight transactions because some of the inputs in
// this block could be referencing other transactions earlier in this
// block which are not yet in the chain.
txInFlight := map[chainhash.Hash]int{}
txNeededSet := make(map[chainhash.Hash]struct{})
// Case 1: ViewpointPrevValidInitial. We need the viewpoint of the
// current chain without the TxTreeRegular of the previous block
// added so we can validate that.
if viewpoint == ViewpointPrevValidInitial {
transactions := parent.Transactions()
for i, tx := range transactions {
txInFlight[*tx.Sha()] = i
}
// Loop through all of the transaction inputs (except for the coinbase
// which has no inputs) collecting them into sets of what is needed and
// what is already known (in-flight).
for i, tx := range transactions[1:] {
for _, txIn := range tx.MsgTx().TxIn {
// It is acceptable for a transaction input to reference
// the output of another transaction in this block only
// if the referenced transaction comes before the
// current one in this block. Add the outputs of the
// referenced transaction as available utxos when this
// is the case. Otherwise, the utxo details are still
// needed.
//
// NOTE: The >= is correct here because i is one less
// than the actual position of the transaction within
// the block due to skipping the coinbase.
originHash := &txIn.PreviousOutPoint.Hash
if inFlightIndex, ok := txInFlight[*originHash]; ok &&
i >= inFlightIndex {
originTx := transactions[inFlightIndex]
view.AddTxOuts(originTx, block.Height(), uint32(i))
continue
}
// Don't request entries that are already in the view
// from the database.
if _, ok := view.entries[*originHash]; ok {
continue
}
txNeededSet[*originHash] = struct{}{}
}
}
// Request the input utxos from the database.
return view.fetchUtxosMain(db, txNeededSet)
}
// Case 2+3: ViewpointPrevValidStake and ViewpointPrevValidStake.
// For ViewpointPrevValidStake, we need the viewpoint of the
// current chain with the TxTreeRegular of the previous block
// added so we can validate the TxTreeStake of the current block.
// For ViewpointPrevInvalidStake, we need the viewpoint of the
// current chain with the TxTreeRegular of the previous block
// missing so we can validate the TxTreeStake of the current block.
if viewpoint == ViewpointPrevValidStake ||
viewpoint == ViewpointPrevInvalidStake {
// We need all of the stake tx txins. None of these are considered
// in-flight in relation to the regular tx tree or to other tx in
// the stake tx tree, so don't do any of those expensive checks and
// just append it to the tx slice.
for _, tx := range block.MsgBlock().STransactions {
isSSGen, _ := stake.IsSSGen(tx)
for i, txIn := range tx.TxIn {
// Ignore stakebases.
if isSSGen && i == 0 {
continue
}
// Add an entry to the transaction store for the needed
// transaction with it set to missing by default.
originHash := &txIn.PreviousOutPoint.Hash
// Don't request entries that are already in the view
// from the database.
if _, ok := view.entries[*originHash]; ok {
continue
}
txNeededSet[*originHash] = struct{}{}
}
}
// Request the input utxos from the database.
return view.fetchUtxosMain(db, txNeededSet)
//.........这里部分代码省略.........