Skip to content

Commit

Permalink
Added basic WIF support
Browse files Browse the repository at this point in the history
  • Loading branch information
mrz1836 committed Oct 1, 2020
1 parent 016946f commit 7d4caf0
Show file tree
Hide file tree
Showing 5 changed files with 322 additions and 1 deletion.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ View the generated [documentation](https://pkg.go.dev/github.com/bitcoinschema/g
- [Create PrivateKey](private_key.go)
- [Create PubKey from PrivateKey](pubkey.go)
- [Script from Address](script.go)
- [WIF to PrivateKey](private_key.go)
- [PrivateKey to WIF](private_key.go)


<details>
Expand Down
24 changes: 24 additions & 0 deletions examples/private_key_to_wif/private_key_to_wif.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package main

import (
"log"

"github.com/bitcoinschema/go-bitcoin"
)

func main() {
// Start with a private key
privateKey, err := bitcoin.CreatePrivateKeyString()
if err != nil {
log.Fatalf("error occurred: %s", err.Error())
}

// Create a wif
var wif string
if wif, err = bitcoin.PrivateKeyToWifString(privateKey); err != nil {
log.Fatalf("error occurred: %s", err.Error())
}

// Success!
log.Printf("private key: %s converted to wif: %s", privateKey, wif)
}
19 changes: 19 additions & 0 deletions examples/wif_to_private_key/wif_to_private_key.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package main

import (
"log"

"github.com/bitcoinschema/go-bitcoin"
)

func main() {

// Convert the wif into a private key
privateKey, err := bitcoin.WifToPrivateKeyString("5KgHn2qiftW5LQgCYFtkbrLYB1FuvisDtacax8NCvumw3UTKdcP")
if err != nil {
log.Fatalf("error occurred: %s", err.Error())
}

// Success!
log.Printf("private key: %s", privateKey)
}
66 changes: 65 additions & 1 deletion private_key.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import (
"math/big"

"github.com/bitcoinsv/bsvd/bsvec"
"github.com/bitcoinsv/bsvd/chaincfg"
"github.com/bitcoinsv/bsvutil"
)

// PrivateKeyFromString turns a private key (hex encoded string) into an bsvec.PrivateKey
Expand All @@ -27,7 +29,7 @@ func PrivateKeyFromString(privateKey string) (*bsvec.PrivateKey, error) {
return &bsvec.PrivateKey{PublicKey: ecdsaPubKey, D: new(big.Int).SetBytes(privateKeyBytes)}, nil
}

// CreatePrivateKey will create a new private key
// CreatePrivateKey will create a new private key (*bsvec.PrivateKey)
func CreatePrivateKey() (*bsvec.PrivateKey, error) {
return bsvec.NewPrivateKey(bsvec.S256())
}
Expand Down Expand Up @@ -61,3 +63,65 @@ func PrivateAndPublicKeys(privateKey string) (*bsvec.PrivateKey, *bsvec.PublicKe
rawKey, publicKey := bsvec.PrivKeyFromBytes(bsvec.S256(), privateKeyBytes)
return rawKey, publicKey, nil
}

// PrivateKeyToWif will convert a private key to a WIF (*bsvutil.WIF)
func PrivateKeyToWif(privateKey string) (*bsvutil.WIF, error) {

// Missing private key
if len(privateKey) == 0 {
return nil, errors.New("missing privateKey")
}

// Decode the private key
decodedKey, err := hex.DecodeString(privateKey)
if err != nil {
return nil, err
}

// Get the private key from bytes
rawKey, _ := bsvec.PrivKeyFromBytes(bsvec.S256(), decodedKey)

// Create a new WIF (error never gets hit since (net) is set correctly)
return bsvutil.NewWIF(rawKey, &chaincfg.MainNetParams, false)
}

// PrivateKeyToWifString will convert a private key to a WIF (string)
func PrivateKeyToWifString(privateKey string) (string, error) {
wif, err := PrivateKeyToWif(privateKey)
if err != nil {
return "", err
}

return wif.String(), nil
}

// WifToPrivateKey will convert a WIF to a private key (*bsvec.PrivateKey)
func WifToPrivateKey(wif string) (*bsvec.PrivateKey, error) {

// Missing wif?
if len(wif) == 0 {
return nil, errors.New("missing wif")
}

// Decode the wif
decodedWif, err := bsvutil.DecodeWIF(wif)
if err != nil {
return nil, err
}

// Return the private key
return decodedWif.PrivKey, nil
}

// WifToPrivateKeyString will convert a WIF to private key (string)
func WifToPrivateKeyString(wif string) (string, error) {

// Convert the wif to private key
privateKey, err := WifToPrivateKey(wif)
if err != nil {
return "", err
}

// Return the hex (string) version of the private key
return hex.EncodeToString(privateKey.Serialize()), nil
}
212 changes: 212 additions & 0 deletions private_key_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -182,3 +182,215 @@ func BenchmarkPrivateAndPublicKeys(b *testing.B) {
_, _, _ = PrivateAndPublicKeys(key)
}
}

// TestPrivateKeyToWif will test the method PrivateKeyToWif()
func TestPrivateKeyToWif(t *testing.T) {

t.Parallel()

// Create the list of tests
var tests = []struct {
input string
expectedWif string
expectedNil bool
expectedError bool
}{
{"", "", true, true},
{"0", "", true, true},
{"000000", "5HpHagT65TZzG1PH3CSu63k8DbpvD8s5ip4nEB3kEsreAbuatmU", false, false},
{"6D792070726976617465206B6579", "5HpHagT65TZzG1PH3CSu63k8DbuTZnNJf6HgyQNymvXmALAsm9s", false, false},
{"54035dd4c7dda99ac473905a3d82f7864322b49bab1ff441cc457183b9bd8azz", "", true, true},
{"54035dd4c7dda99ac473905a3d82f7864322b49bab1ff441cc457183b9bd8abd", "5JTHas7yTFMBLqgFogxZFf8Vc5uKEbkE7yQAQ2g3xPHo2sNG1Ei", false, false},
}

// Run tests
for _, test := range tests {
if wif, err := PrivateKeyToWif(test.input); err != nil && !test.expectedError {
t.Errorf("%s Failed: [%s] inputted and error not expected but got: %s", t.Name(), test.input, err.Error())
} else if err == nil && test.expectedError {
t.Errorf("%s Failed: [%s] inputted and error was expected", t.Name(), test.input)
} else if wif == nil && !test.expectedNil {
t.Errorf("%s Failed: [%s] inputted and was nil but not expected", t.Name(), test.input)
} else if wif != nil && test.expectedNil {
t.Errorf("%s Failed: [%s] inputted and was NOT nil but expected to be nil", t.Name(), test.input)
} else if wif != nil && wif.String() != test.expectedWif {
t.Errorf("%s Failed: [%s] inputted [%s] expected but failed comparison of keys, got: %s", t.Name(), test.input, test.expectedWif, wif.String())
}
}

}

// ExamplePrivateKeyToWif example using PrivateKeyToWif()
func ExamplePrivateKeyToWif() {
wif, err := PrivateKeyToWif("54035dd4c7dda99ac473905a3d82f7864322b49bab1ff441cc457183b9bd8abd")
if err != nil {
fmt.Printf("error occurred: %s", err.Error())
return
}
fmt.Printf("converted wif: %s", wif.String())

// Output:converted wif: 5JTHas7yTFMBLqgFogxZFf8Vc5uKEbkE7yQAQ2g3xPHo2sNG1Ei
}

// BenchmarkPrivateKeyToWif benchmarks the method PrivateKeyToWif()
func BenchmarkPrivateKeyToWif(b *testing.B) {
key, _ := CreatePrivateKeyString()
for i := 0; i < b.N; i++ {
_, _ = PrivateKeyToWif(key)
}
}

// TestPrivateKeyToWifString will test the method PrivateKeyToWifString()
func TestPrivateKeyToWifString(t *testing.T) {

t.Parallel()

// Create the list of tests
var tests = []struct {
input string
expectedWif string
expectedError bool
}{
{"", "", true},
{"0", "", true},
{"000000", "5HpHagT65TZzG1PH3CSu63k8DbpvD8s5ip4nEB3kEsreAbuatmU", false},
{"6D792070726976617465206B6579", "5HpHagT65TZzG1PH3CSu63k8DbuTZnNJf6HgyQNymvXmALAsm9s", false},
{"54035dd4c7dda99ac473905a3d82f7864322b49bab1ff441cc457183b9bd8azz", "", true},
{"54035dd4c7dda99ac473905a3d82f7864322b49bab1ff441cc457183b9bd8abd", "5JTHas7yTFMBLqgFogxZFf8Vc5uKEbkE7yQAQ2g3xPHo2sNG1Ei", false},
}

// Run tests
for _, test := range tests {
if wif, err := PrivateKeyToWifString(test.input); err != nil && !test.expectedError {
t.Errorf("%s Failed: [%s] inputted and error not expected but got: %s", t.Name(), test.input, err.Error())
} else if err == nil && test.expectedError {
t.Errorf("%s Failed: [%s] inputted and error was expected", t.Name(), test.input)
} else if wif != test.expectedWif {
t.Errorf("%s Failed: [%s] inputted [%s] expected but failed comparison of keys, got: %s", t.Name(), test.input, test.expectedWif, wif)
}
}

}

// ExamplePrivateKeyToWifString example using PrivateKeyToWifString()
func ExamplePrivateKeyToWifString() {
wif, err := PrivateKeyToWifString("54035dd4c7dda99ac473905a3d82f7864322b49bab1ff441cc457183b9bd8abd")
if err != nil {
fmt.Printf("error occurred: %s", err.Error())
return
}
fmt.Printf("converted wif: %s", wif)

// Output:converted wif: 5JTHas7yTFMBLqgFogxZFf8Vc5uKEbkE7yQAQ2g3xPHo2sNG1Ei
}

// BenchmarkPrivateKeyToWifString benchmarks the method PrivateKeyToWifString()
func BenchmarkPrivateKeyToWifString(b *testing.B) {
key, _ := CreatePrivateKeyString()
for i := 0; i < b.N; i++ {
_, _ = PrivateKeyToWifString(key)
}
}

// TestWifToPrivateKey will test the method WifToPrivateKey()
func TestWifToPrivateKey(t *testing.T) {
t.Parallel()

// Create the list of tests
var tests = []struct {
input string
expectedKey string
expectedNil bool
expectedError bool
}{
{"", "", true, true},
{"0", "", true, true},
{"5HpHagT65TZzG1PH3CSu63k8DbpvD8s5ip4nEB3kEsreAbuatmU", "0000000000000000000000000000000000000000000000000000000000000000", false, false},
{"5HpHagT65TZzG1PH3CSu63k8DbuTZnNJf6HgyQNymvXmALAsm9s", "0000000000000000000000000000000000006d792070726976617465206b6579", false, false},
{"54035dd4c7dda99ac473905a3d82f7864322b49bab1ff441cc457183b9bd8azz", "", true, true},
{"5JTHas7yTFMBLqgFogxZFf8Vc5uKEbkE7yQAQ2g3xPHo2sNG1Ei", "54035dd4c7dda99ac473905a3d82f7864322b49bab1ff441cc457183b9bd8abd", false, false},
}

// Run tests
for _, test := range tests {
if privateKey, err := WifToPrivateKey(test.input); err != nil && !test.expectedError {
t.Errorf("%s Failed: [%s] inputted and error not expected but got: %s", t.Name(), test.input, err.Error())
} else if err == nil && test.expectedError {
t.Errorf("%s Failed: [%s] inputted and error was expected", t.Name(), test.input)
} else if privateKey == nil && !test.expectedNil {
t.Errorf("%s Failed: [%s] inputted and was nil but not expected", t.Name(), test.input)
} else if privateKey != nil && test.expectedNil {
t.Errorf("%s Failed: [%s] inputted and was NOT nil but expected to be nil", t.Name(), test.input)
} else if privateKey != nil && hex.EncodeToString(privateKey.Serialize()) != test.expectedKey {
t.Errorf("%s Failed: [%s] inputted [%s] expected but failed comparison of keys, got: %s", t.Name(), test.input, test.expectedKey, hex.EncodeToString(privateKey.Serialize()))
}
}
}

// ExampleWifToPrivateKey example using WifToPrivateKey()
func ExampleWifToPrivateKey() {
privateKey, err := WifToPrivateKey("5JTHas7yTFMBLqgFogxZFf8Vc5uKEbkE7yQAQ2g3xPHo2sNG1Ei")
if err != nil {
fmt.Printf("error occurred: %s", err.Error())
return
}
fmt.Printf("private key: %s", hex.EncodeToString(privateKey.Serialize()))

// Output:private key: 54035dd4c7dda99ac473905a3d82f7864322b49bab1ff441cc457183b9bd8abd
}

// BenchmarkWifToPrivateKey benchmarks the method WifToPrivateKey()
func BenchmarkWifToPrivateKey(b *testing.B) {
for i := 0; i < b.N; i++ {
_, _ = WifToPrivateKey("5JTHas7yTFMBLqgFogxZFf8Vc5uKEbkE7yQAQ2g3xPHo2sNG1Ei")
}
}

// TestWifToPrivateKeyString will test the method WifToPrivateKeyString()
func TestWifToPrivateKeyString(t *testing.T) {
t.Parallel()

// Create the list of tests
var tests = []struct {
input string
expectedKey string
expectedError bool
}{
{"", "", true},
{"0", "", true},
{"5HpHagT65TZzG1PH3CSu63k8DbpvD8s5ip4nEB3kEsreAbuatmU", "0000000000000000000000000000000000000000000000000000000000000000", false},
{"5HpHagT65TZzG1PH3CSu63k8DbuTZnNJf6HgyQNymvXmALAsm9s", "0000000000000000000000000000000000006d792070726976617465206b6579", false},
{"54035dd4c7dda99ac473905a3d82f7864322b49bab1ff441cc457183b9bd8azz", "", true},
{"5JTHas7yTFMBLqgFogxZFf8Vc5uKEbkE7yQAQ2g3xPHo2sNG1Ei", "54035dd4c7dda99ac473905a3d82f7864322b49bab1ff441cc457183b9bd8abd", false},
}

// Run tests
for _, test := range tests {
if privateKey, err := WifToPrivateKeyString(test.input); err != nil && !test.expectedError {
t.Errorf("%s Failed: [%s] inputted and error not expected but got: %s", t.Name(), test.input, err.Error())
} else if err == nil && test.expectedError {
t.Errorf("%s Failed: [%s] inputted and error was expected", t.Name(), test.input)
} else if privateKey != test.expectedKey {
t.Errorf("%s Failed: [%s] inputted [%s] expected but failed comparison of keys, got: %s", t.Name(), test.input, test.expectedKey, privateKey)
}
}
}

// ExampleWifToPrivateKeyString example using WifToPrivateKeyString()
func ExampleWifToPrivateKeyString() {
privateKey, err := WifToPrivateKeyString("5JTHas7yTFMBLqgFogxZFf8Vc5uKEbkE7yQAQ2g3xPHo2sNG1Ei")
if err != nil {
fmt.Printf("error occurred: %s", err.Error())
return
}
fmt.Printf("private key: %s", privateKey)

// Output:private key: 54035dd4c7dda99ac473905a3d82f7864322b49bab1ff441cc457183b9bd8abd
}

// BenchmarkWifToPrivateKeyString benchmarks the method WifToPrivateKeyString()
func BenchmarkWifToPrivateKeyString(b *testing.B) {
for i := 0; i < b.N; i++ {
_, _ = WifToPrivateKeyString("5JTHas7yTFMBLqgFogxZFf8Vc5uKEbkE7yQAQ2g3xPHo2sNG1Ei")
}
}

0 comments on commit 7d4caf0

Please sign in to comment.