// handleMissedTickets receives a list of hashes and some block information // and submits it to the wstakemgr to handle SSRtx production. func (w *Wallet) handleMissedTickets(dbtx walletdb.ReadWriteTx, blockHash *chainhash.Hash, blockHeight int64, tickets []*chainhash.Hash) error { stakemgrNs := dbtx.ReadWriteBucket(wstakemgrNamespaceKey) addrmgrNs := dbtx.ReadBucket(waddrmgrNamespaceKey) if !w.StakeMiningEnabled { return nil } if blockHeight >= w.chainParams.StakeValidationHeight+1 && w.StakeMiningEnabled { ntfns, err := w.StakeMgr.HandleMissedTicketsNtfn(stakemgrNs, addrmgrNs, blockHash, blockHeight, tickets, w.AllowHighFees) if ntfns != nil { // Send notifications for newly created revocations by the RPC. for _, ntfn := range ntfns { if ntfn != nil { // Inform the console that we've revoked our ticket. log.Infof("Revoked missed ticket %v (tx hash: %v)", ntfn.SStxIn, ntfn.TxHash) } } } return err } return nil }
// handleWinningTickets receives a list of hashes and some block information // and submits it to the wstakemgr to handle SSGen production. func (w *Wallet) handleWinningTickets(dbtx walletdb.ReadWriteTx, blockHash *chainhash.Hash, blockHeight int64, tickets []*chainhash.Hash) error { addrmgrNs := dbtx.ReadBucket(waddrmgrNamespaceKey) stakemgrNs := dbtx.ReadWriteBucket(wstakemgrNamespaceKey) txmgrNs := dbtx.ReadBucket(wtxmgrNamespaceKey) topHash, _ := w.TxStore.MainChainTip(txmgrNs) // Even if stake voting is disabled, we should still store eligible // tickets for the current top block. // TODO The behavior of this is not quite right if tons of blocks // are coming in quickly, because the transaction store will end up // out of sync with the voting channel here. This should probably // be fixed somehow, but this should be stable for networks that // are voting at normal block speeds. if blockHeight >= w.chainParams.StakeValidationHeight-1 && topHash == *blockHash { w.SetCurrentVotingInfo(blockHash, blockHeight, tickets) } if blockHeight >= w.chainParams.StakeValidationHeight-1 && w.StakeMiningEnabled { ntfns, err := w.StakeMgr.HandleWinningTicketsNtfn( stakemgrNs, addrmgrNs, blockHash, blockHeight, tickets, w.VoteBits, w.AllowHighFees, ) if ntfns != nil { // Send notifications for newly created votes by the RPC. for _, ntfn := range ntfns { // Inform the console that we've voted, too. log.Infof("Voted on block %v (height %v) using ticket %v "+ "(vote hash: %v)", ntfn.BlockHash, ntfn.Height, ntfn.SStxIn, ntfn.TxHash) } } return err } return nil }
// switchToSideChain performs a chain switch, switching the main chain to the // in-memory side chain. The old side chain becomes the new main chain. func (w *Wallet) switchToSideChain(dbtx walletdb.ReadWriteTx) error { addrmgrNs := dbtx.ReadBucket(waddrmgrNamespaceKey) txmgrNs := dbtx.ReadWriteBucket(wtxmgrNamespaceKey) sideChain := w.sideChain if len(sideChain) == 0 { return errors.New("no side chain to switch to") } sideChainForkHeight := sideChain[0].headerData.SerializedHeader.Height() // Notify detached blocks for each removed block, in reversed order. _, tipHeight := w.TxStore.MainChainTip(txmgrNs) for i := tipHeight; i >= sideChainForkHeight; i-- { hash, err := w.TxStore.GetMainChainBlockHashForHeight(txmgrNs, i) if err != nil { return err } w.NtfnServer.notifyDetachedBlock(&hash) } // Remove blocks on the current main chain that are at or above the // height of the block that begins the side chain. err := w.TxStore.Rollback(txmgrNs, addrmgrNs, sideChainForkHeight) if err != nil { return err } // Extend the main chain with each sidechain block. for i := range sideChain { scBlock := &sideChain[i] err = w.extendMainChain(dbtx, &scBlock.headerData, scBlock.transactions) if err != nil { return err } } return nil }