예제 #1
1
// generateFund is the high-level logic for funding any P2SH address with the 'go-bitcoin-multisig fund' subcommand.
// Takes flagPrivateKey (private key of input Bitcoins to fund with), flagInputTx (input transaction hash of
// Bitcoins to fund with), flagAmount (amount in Satoshis to send, with balance left over from input being used
// as transaction fee) and flagP2SHDestination (destination P2SH multisig address which is being funded) as arguments.
func generateFund(flagPrivateKey string, flagInputTx string, flagAmount int, flagP2SHDestination string) string {
	//Get private key as decoded raw bytes
	privateKey := base58check.Decode(flagPrivateKey)
	//In order to construct the raw transaction we need the input transaction hash,
	//the P2SH destination address, the number of satoshis to send, and the scriptSig
	//which is temporarily (prior to signing) the ScriptPubKey of the input transaction.
	publicKey, err := btcutils.NewPublicKey(privateKey)
	if err != nil {
		log.Fatal(err)
	}
	publicKeyHash, err := btcutils.Hash160(publicKey)
	if err != nil {
		log.Fatal(err)
	}
	tempScriptSig, err := btcutils.NewP2PKHScriptPubKey(publicKeyHash)
	if err != nil {
		log.Fatal(err)
	}
	redeemScriptHash := base58check.Decode(flagP2SHDestination)
	//Create our scriptPubKey
	scriptPubKey, err := btcutils.NewP2SHScriptPubKey(redeemScriptHash)
	if err != nil {
		log.Fatal(err)
	}
	//Create unsigned raw transaction
	rawTransaction, err := btcutils.NewRawTransaction(flagInputTx, flagAmount, tempScriptSig, scriptPubKey)
	if err != nil {
		log.Fatal(err)
	}
	//After completing the raw transaction, we append
	//SIGHASH_ALL in little-endian format to the end of the raw transaction.
	hashCodeType, err := hex.DecodeString("01000000")
	if err != nil {
		log.Fatal(err)
	}
	var rawTransactionBuffer bytes.Buffer
	rawTransactionBuffer.Write(rawTransaction)
	rawTransactionBuffer.Write(hashCodeType)
	rawTransactionWithHashCodeType := rawTransactionBuffer.Bytes()
	//Sign the raw transaction, and output it to the console.
	finalTransaction, err := signP2PKHTransaction(rawTransactionWithHashCodeType, privateKey, scriptPubKey, flagInputTx, flagAmount)
	if err != nil {
		log.Fatal(err)
	}
	finalTransactionHex := hex.EncodeToString(finalTransaction)

	return finalTransactionHex
}
예제 #2
0
// signP2PKHTransaction signs a raw P2PKH transaction, given a private key and the scriptPubKey, inputTx and amount
// to construct the final transaction.
func signP2PKHTransaction(rawTransaction []byte, privateKey []byte, scriptPubKey []byte, inputTx string, amount int) ([]byte, error) {
	publicKey, err := btcutils.NewPublicKey(privateKey)
	if err != nil {
		return nil, err
	}
	signature, err := btcutils.NewSignature(rawTransaction, privateKey)
	if err != nil {
		return nil, err
	}
	hashCodeType, err := hex.DecodeString("01")
	if err != nil {
		return nil, err
	}
	//signatureLength is +1 to add hashCodeType
	signatureLength := byte(len(signature) + 1)
	//Create scriptSig
	var buffer bytes.Buffer
	buffer.WriteByte(signatureLength)
	buffer.Write(signature)
	buffer.WriteByte(hashCodeType[0])
	buffer.WriteByte(byte(len(publicKey)))
	buffer.Write(publicKey)
	scriptSig := buffer.Bytes()
	//Finally create transaction with actual scriptSig
	signedRawTransaction, err := btcutils.NewRawTransaction(inputTx, amount, scriptSig, scriptPubKey)
	if err != nil {
		return nil, err
	}
	return signedRawTransaction, nil
}
예제 #3
0
// generateKeys is the high-level logic for generating public/private key pairs with the 'go-bitcoin-multisig keys' subcommand.
// Takes flagCount (desired number of key pairs) and flagConcise (true hides warnings and helpful messages for conciseness)
// as arguments.
func generateKeys(flagKeyCount int) ([]string, []string, []string) {
	publicKeyHexs := make([]string, flagKeyCount)
	publicAddresses := make([]string, flagKeyCount)
	privateKeyWIFs := make([]string, flagKeyCount)

	for i := 0; i <= flagKeyCount-1; i++ {
		//Generate private key
		privateKey := btcutils.NewPrivateKey()
		//Generate public key from private key
		publicKey, err := btcutils.NewPublicKey(privateKey)
		if err != nil {
			log.Fatal(err)
		}
		//Get hex encoded version of public key
		publicKeyHexs[i] = hex.EncodeToString(publicKey)
		//Get public address by hashing with SHA256 and RIPEMD160 and base58 encoding with mainnet prefix 00
		publicKeyHash, err := btcutils.Hash160(publicKey)
		if err != nil {
			log.Fatal(err)
		}
		publicAddresses[i] = base58check.Encode("00", publicKeyHash)
		//Get private key in Wallet Import Format (WIF) by base58 encoding with prefix 80
		privateKeyWIFs[i] = base58check.Encode("80", privateKey)
	}

	return privateKeyWIFs, publicKeyHexs, publicAddresses
}