コード例 #1
0
ファイル: ticketdb.go プロジェクト: zebbra2014/dcrd
// GetLiveTicketsForAddress gets all currently active tickets for a given
// address.
func (tmdb *TicketDB) GetLiveTicketsForAddress(
	address dcrutil.Address) ([]chainhash.Hash, error) {
	tmdb.mtx.Lock()
	defer tmdb.mtx.Unlock()

	var ltfa []chainhash.Hash
	for i := 0; i < BucketsSize; i++ {
		for _, ticket := range tmdb.maps.ticketMap[i] {
			// Load the ticket from the database and find the address that it's
			// going to.
			txReply, err := tmdb.database.FetchTxBySha(&ticket.SStxHash)
			if err != nil {
				return nil, err
			}

			_, addr, _, err :=
				txscript.ExtractPkScriptAddrs(txReply[0].Tx.TxOut[0].Version,
					txReply[0].Tx.TxOut[0].PkScript, tmdb.chainParams)
			if err != nil {
				return nil, err
			}

			// Compare the HASH160 result and see if it's equal.
			if bytes.Equal(addr[0].ScriptAddress(), address.ScriptAddress()) {
				ltfa = append(ltfa, ticket.SStxHash)
			}
		}
	}

	return ltfa, nil
}
コード例 #2
0
ファイル: standard.go プロジェクト: zebbra2014/dcrd
// PayToSSRtx creates a new script to pay a transaction output to a
// public key hash, but tags the output with OP_SSRTX. For use in constructing
// valid SSRtx.
func PayToSSRtx(addr dcrutil.Address) ([]byte, error) {
	if addr == nil {
		return nil, ErrUnsupportedAddress
	}

	// Only pay to pubkey hash and pay to script hash are
	// supported.
	scriptType := PubKeyHashTy
	switch addr := addr.(type) {
	case *dcrutil.AddressPubKeyHash:
		if addr.DSA(addr.Net()) != chainec.ECTypeSecp256k1 {
			return nil, ErrUnsupportedAddress
		}
		break
	case *dcrutil.AddressScriptHash:
		scriptType = ScriptHashTy
		break
	default:
		return nil, ErrUnsupportedAddress
	}

	hash := addr.ScriptAddress()

	if scriptType == PubKeyHashTy {
		return NewScriptBuilder().AddOp(OP_SSRTX).AddOp(OP_DUP).
			AddOp(OP_HASH160).AddData(hash).AddOp(OP_EQUALVERIFY).
			AddOp(OP_CHECKSIG).Script()
	}
	return NewScriptBuilder().AddOp(OP_SSRTX).AddOp(OP_HASH160).
		AddData(hash).AddOp(OP_EQUAL).Script()
}
コード例 #3
0
ファイル: stake.go プロジェクト: decred/dcrwallet
// dumpSStxHashes dumps the hashes of all owned SStxs for some address.
func (s *StakeStore) dumpSStxHashesForAddress(ns walletdb.ReadBucket, addr dcrutil.Address) ([]chainhash.Hash, error) {
	// Extract the HASH160 script hash; if it's not 20 bytes
	// long, return an error.
	hash160 := addr.ScriptAddress()
	if len(hash160) != 20 {
		str := "stake store is closed"
		return nil, stakeStoreError(ErrInput, str, nil)
	}
	_, addrIsP2SH := addr.(*dcrutil.AddressScriptHash)

	allTickets := s.dumpSStxHashes()
	var ticketsForAddr []chainhash.Hash

	// Access the database and store the result locally.
	for _, h := range allTickets {
		thisHash160, p2sh, err := fetchSStxRecordSStxTicketHash160(ns, &h)
		if err != nil {
			str := "failure getting ticket 0th out script hashes from db"
			return nil, stakeStoreError(ErrDatabase, str, err)
		}
		if addrIsP2SH != p2sh {
			continue
		}

		if bytes.Equal(hash160, thisHash160) {
			ticketsForAddr = append(ticketsForAddr, h)
		}
	}

	return ticketsForAddr, nil
}
コード例 #4
0
ファイル: stake.go プロジェクト: frankbraun/dcrwallet
// dumpSStxHashes dumps the hashes of all owned SStxs for some address.
func (s *StakeStore) dumpSStxHashesForAddress(addr dcrutil.Address) ([]chainhash.Hash, error) {
	// Extract the HASH160 script hash; if it's not 20 bytes
	// long, return an error.
	scriptHash := addr.ScriptAddress()
	if len(scriptHash) != 20 {
		str := "stake store is closed"
		return nil, stakeStoreError(ErrInput, str, nil)
	}

	var err error
	allTickets := s.dumpSStxHashes()
	var ticketsForAddr []chainhash.Hash

	// Access the database and store the result locally.
	err = s.namespace.View(func(tx walletdb.Tx) error {
		var err error
		var thisScrHash []byte
		for _, h := range allTickets {
			thisScrHash, err = fetchSStxRecordSStxTicketScriptHash(tx, &h)
			if err != nil {
				return err
			}
			if bytes.Equal(scriptHash, thisScrHash) {
				ticketsForAddr = append(ticketsForAddr, h)
			}
		}
		return nil
	})
	if err != nil {
		str := "failure getting ticket 0th out script hashes from db"
		return nil, stakeStoreError(ErrDatabase, str, err)
	}

	return ticketsForAddr, nil
}
コード例 #5
0
ファイル: stake.go プロジェクト: decred/dcrwallet
// stakePoolUserInfo returns the stake pool user information for a given stake
// pool user, keyed to their P2SH voting address.
func (s *StakeStore) stakePoolUserInfo(ns walletdb.ReadBucket, user dcrutil.Address) (*StakePoolUser, error) {
	_, isScriptHash := user.(*dcrutil.AddressScriptHash)
	_, isP2PKH := user.(*dcrutil.AddressPubKeyHash)
	if !(isScriptHash || isP2PKH) {
		str := fmt.Sprintf("user %v is invalid", user.EncodeAddress())
		return nil, stakeStoreError(ErrBadPoolUserAddr, str, nil)
	}
	scriptHashB := user.ScriptAddress()
	scriptHash := new([20]byte)
	copy(scriptHash[:], scriptHashB)

	stakePoolUser := new(StakePoolUser)

	// Catch missing user errors below and blank out the stake
	// pool user information for the section if the user has
	// no entries.
	missingValidTickets, missingInvalidTickets := false, false

	userTickets, fetchErrVal := fetchStakePoolUserTickets(ns, *scriptHash)
	if fetchErrVal != nil {
		stakeMgrErr, is := fetchErrVal.(StakeStoreError)
		if is {
			missingValidTickets = stakeMgrErr.ErrorCode ==
				ErrPoolUserTicketsNotFound
		} else {
			return nil, fetchErrVal
		}
	}
	if missingValidTickets {
		userTickets = make([]*PoolTicket, 0)
	}

	invalTickets, fetchErrInval := fetchStakePoolUserInvalTickets(ns,
		*scriptHash)
	if fetchErrInval != nil {
		stakeMgrErr, is := fetchErrInval.(StakeStoreError)
		if is {
			missingInvalidTickets = stakeMgrErr.ErrorCode ==
				ErrPoolUserInvalTcktsNotFound
		} else {
			return nil, fetchErrInval
		}
	}
	if missingInvalidTickets {
		invalTickets = make([]*chainhash.Hash, 0)
	}

	stakePoolUser.Tickets = userTickets
	stakePoolUser.InvalidTickets = invalTickets

	return stakePoolUser, nil
}
コード例 #6
0
ファイル: stake.go プロジェクト: decred/dcrwallet
// updateStakePoolUserInvalTickets updates the list of invalid stake pool
// tickets for a given user. If the ticket does not currently exist in the
// database, it adds it.
func (s *StakeStore) updateStakePoolUserInvalTickets(ns walletdb.ReadWriteBucket, user dcrutil.Address, ticket *chainhash.Hash) error {
	_, isScriptHash := user.(*dcrutil.AddressScriptHash)
	_, isP2PKH := user.(*dcrutil.AddressPubKeyHash)
	if !(isScriptHash || isP2PKH) {
		str := fmt.Sprintf("user %v is invalid", user.EncodeAddress())
		return stakeStoreError(ErrBadPoolUserAddr, str, nil)
	}
	scriptHashB := user.ScriptAddress()
	scriptHash := new([20]byte)
	copy(scriptHash[:], scriptHashB)

	return updateStakePoolInvalUserTickets(ns, *scriptHash, ticket)
}
コード例 #7
0
ファイル: standard.go プロジェクト: zebbra2014/dcrd
// GenerateSStxAddrPush generates an OP_RETURN push for SSGen payment addresses in
// an SStx.
func GenerateSStxAddrPush(addr dcrutil.Address, amount dcrutil.Amount,
	limits uint16) ([]byte, error) {
	if addr == nil {
		return nil, ErrUnsupportedAddress
	}

	// Only pay to pubkey hash and pay to script hash are
	// supported.
	scriptType := PubKeyHashTy
	switch addr := addr.(type) {
	case *dcrutil.AddressPubKeyHash:
		if addr.DSA(addr.Net()) != chainec.ECTypeSecp256k1 {
			return nil, ErrUnsupportedAddress
		}
		break
	case *dcrutil.AddressScriptHash:
		scriptType = ScriptHashTy
		break
	default:
		return nil, ErrUnsupportedAddress
	}

	// Prefix
	dataPushes := []byte{
		0x6a, // OP_RETURN
		0x1e, // OP_DATA_30
	}

	hash := addr.ScriptAddress()

	amountBuffer := make([]byte, 8)
	binary.LittleEndian.PutUint64(amountBuffer, uint64(amount))

	// Set the bit flag indicating pay to script hash.
	if scriptType == ScriptHashTy {
		amountBuffer[7] |= 1 << 7
	}

	limitsBuffer := make([]byte, 2)
	binary.LittleEndian.PutUint16(limitsBuffer, limits)

	// Concatenate the prefix, pubkeyhash, and amount.
	addrOut := append(dataPushes, hash...)
	addrOut = append(addrOut, amountBuffer...)
	addrOut = append(addrOut, limitsBuffer...)

	return addrOut, nil
}
コード例 #8
0
ファイル: standard.go プロジェクト: zebbra2014/dcrd
// PayToAddrScript creates a new script to pay a transaction output to a the
// specified address.
func PayToAddrScript(addr dcrutil.Address) ([]byte, error) {
	switch addr := addr.(type) {
	case *dcrutil.AddressPubKeyHash:
		if addr == nil {
			return nil, ErrUnsupportedAddress
		}
		switch addr.DSA(addr.Net()) {
		case chainec.ECTypeSecp256k1:
			return payToPubKeyHashScript(addr.ScriptAddress())
		case chainec.ECTypeEdwards:
			return payToPubKeyHashEdwardsScript(addr.ScriptAddress())
		case chainec.ECTypeSecSchnorr:
			return payToPubKeyHashSchnorrScript(addr.ScriptAddress())
		}

	case *dcrutil.AddressScriptHash:
		if addr == nil {
			return nil, ErrUnsupportedAddress
		}
		return payToScriptHashScript(addr.ScriptAddress())

	case *dcrutil.AddressSecpPubKey:
		if addr == nil {
			return nil, ErrUnsupportedAddress
		}
		return payToPubKeyScript(addr.ScriptAddress())

	case *dcrutil.AddressEdwardsPubKey:
		if addr == nil {
			return nil, ErrUnsupportedAddress
		}
		return payToEdwardsPubKeyScript(addr.ScriptAddress())

	case *dcrutil.AddressSecSchnorrPubKey:
		if addr == nil {
			return nil, ErrUnsupportedAddress
		}
		return payToSchnorrPubKeyScript(addr.ScriptAddress())
	}

	return nil, ErrUnsupportedAddress
}