diff --git a/pubkey.go b/pubkey.go index 9231522..7e7a125 100644 --- a/pubkey.go +++ b/pubkey.go @@ -2,6 +2,9 @@ package bitcoin import ( "encoding/hex" + "errors" + + "github.com/bitcoinsv/bsvd/bsvec" ) // PubKeyFromPrivateKey will derive a pubKey (hex encoded) from a given private key @@ -13,3 +16,21 @@ func PubKeyFromPrivateKey(privateKey string) (string, error) { return hex.EncodeToString(rawKey.PubKey().SerializeCompressed()), nil } + +// PubKeyFromString will convert a pubKey (string) into a pubkey (*bsvec.PublicKey) +func PubKeyFromString(pubKey string) (*bsvec.PublicKey, error) { + + // Invalid pubKey + if len(pubKey) == 0 { + return nil, errors.New("missing pubkey") + } + + // Decode from hex string + decoded, err := hex.DecodeString(pubKey) + if err != nil { + return nil, err + } + + // Parse into a pubKey + return bsvec.ParsePubKey(decoded, bsvec.S256()) +} diff --git a/pubkey_test.go b/pubkey_test.go index b4b71e5..2c3ab6d 100644 --- a/pubkey_test.go +++ b/pubkey_test.go @@ -1,6 +1,7 @@ package bitcoin import ( + "encoding/hex" "fmt" "testing" ) @@ -50,3 +51,55 @@ func BenchmarkPubKeyFromPrivateKey(b *testing.B) { _, _ = PubKeyFromPrivateKey(key) } } + +// TestPubKeyFromString will test the method PubKeyFromString() +func TestPubKeyFromString(t *testing.T) { + + t.Parallel() + + // Create the list of tests + var tests = []struct { + inputKey string + expectedPubKey string + expectedNil bool + expectedError bool + }{ + {"", "", true, true}, + {"0", "", true, true}, + {"00000", "", true, true}, + {"031b8c93100d35bd448f4646cc4678f278351b439b52b303ea31ec9edb5475e73f", "031b8c93100d35bd448f4646cc4678f278351b439b52b303ea31ec9edb5475e73f", false, false}, + } + + // Run tests + for _, test := range tests { + if pubKey, err := PubKeyFromString(test.inputKey); err != nil && !test.expectedError { + t.Errorf("%s Failed: [%s] inputted and error not expected but got: %s", t.Name(), test.inputKey, err.Error()) + } else if err == nil && test.expectedError { + t.Errorf("%s Failed: [%s] inputted and error was expected", t.Name(), test.inputKey) + } else if pubKey != nil && test.expectedNil { + t.Errorf("%s Failed: [%s] inputted and nil was expected", t.Name(), test.inputKey) + } else if pubKey == nil && !test.expectedNil { + t.Errorf("%s Failed: [%s] inputted and nil was NOT expected", t.Name(), test.inputKey) + } else if pubKey != nil && hex.EncodeToString(pubKey.SerializeCompressed()) != test.expectedPubKey { + t.Errorf("%s Failed: [%s] inputted and [%s] expected, but got: %s", t.Name(), test.inputKey, test.expectedPubKey, hex.EncodeToString(pubKey.SerializeCompressed())) + } + } +} + +// ExamplePubKeyFromString example using PubKeyFromString() +func ExamplePubKeyFromString() { + pubKey, err := PubKeyFromString("031b8c93100d35bd448f4646cc4678f278351b439b52b303ea31ec9edb5475e73f") + if err != nil { + fmt.Printf("error occurred: %s", err.Error()) + return + } + fmt.Printf("pubkey from string: %s", hex.EncodeToString(pubKey.SerializeCompressed())) + // Output:pubkey from string: 031b8c93100d35bd448f4646cc4678f278351b439b52b303ea31ec9edb5475e73f +} + +// BenchmarkPubKeyFromString benchmarks the method PubKeyFromString() +func BenchmarkPubKeyFromString(b *testing.B) { + for i := 0; i < b.N; i++ { + _, _ = PubKeyFromString("031b8c93100d35bd448f4646cc4678f278351b439b52b303ea31ec9edb5475e73f") + } +}