Skip to content

Commit

Permalink
Merge pull request #33 from BitcoinSchema/v2
Browse files Browse the repository at this point in the history
Feature: v2 Alpha Release
  • Loading branch information
mrz1836 authored Feb 3, 2022
2 parents 38480d8 + 10a5999 commit b97670d
Show file tree
Hide file tree
Showing 29 changed files with 404 additions and 363 deletions.
61 changes: 32 additions & 29 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ View the generated [documentation](https://pkg.go.dev/github.com/bitcoinschema/g
### Features

- **Addresses**
- [Address from PrivateKey (bsvec.PrivateKey)](address.go)
- [Address from PrivateKey (bec.PrivateKey)](address.go)
- [Address from Script](address.go)
- **Encryption**
- [Encrypt With Private Key](encryption.go)
Expand Down Expand Up @@ -97,7 +97,7 @@ View the generated [documentation](https://pkg.go.dev/github.com/bitcoinschema/g
<br/>

- [bitcoinsv/bsvd](https://github.com/bitcoinsv/bsvd)
- [bitcoinsv/bsvutil](https://github.com/bitcoinsv/bsvutil)
- [libsv/go-bk](https://github.com/libsv/go-bk)
- [libsv/go-bt](https://github.com/libsv/go-bt)
</details>

Expand Down Expand Up @@ -126,33 +126,36 @@ make help
List of all current commands:

```text
all Runs multiple commands
clean Remove previous builds and any test cache data
clean-mods Remove all the Go mod cache
coverage Shows the test coverage
generate Runs the go generate command in the base of the repo
godocs Sync the latest tag with GoDocs
help Show this help message
install Install the application
install-go Install the application (Using Native Go)
lint Run the golangci-lint application (install if not found)
release Full production release (creates release in Github)
release Runs common.release then runs godocs
release-snap Test the full release (build binaries)
release-test Full production test release (everything except deploy)
replace-version Replaces the version in HTML/JS (pre-deploy)
tag Generate a new tag and push (tag version=0.0.0)
tag-remove Remove a tag if found (tag-remove version=0.0.0)
tag-update Update an existing tag to current commit (tag-update version=0.0.0)
test Runs vet, lint and ALL tests
test-ci Runs all tests via CI (exports coverage)
test-ci-no-race Runs all tests via CI (no race) (exports coverage)
test-ci-short Runs unit tests via CI (exports coverage)
test-short Runs vet, lint and tests (excludes integration tests)
test-unit Runs tests and outputs coverage
uninstall Uninstall the application (and remove files)
update-linter Update the golangci-lint package (macOS only)
vet Run the Go vet application
all Runs multiple commands
clean Remove previous builds and any test cache data
clean-mods Remove all the Go mod cache
coverage Shows the test coverage
diff Show the git diff
generate Runs the go generate command in the base of the repo
godocs Sync the latest tag with GoDocs
help Show this help message
install Install the application
install-go Install the application (Using Native Go)
install-releaser Install the GoReleaser application
lint Run the golangci-lint application (install if not found)
release Full production release (creates release in Github)
release Runs common.release then runs godocs
release-snap Test the full release (build binaries)
release-test Full production test release (everything except deploy)
replace-version Replaces the version in HTML/JS (pre-deploy)
tag Generate a new tag and push (tag version=0.0.0)
tag-remove Remove a tag if found (tag-remove version=0.0.0)
tag-update Update an existing tag to current commit (tag-update version=0.0.0)
test Runs lint and ALL tests
test-ci Runs all tests via CI (exports coverage)
test-ci-no-race Runs all tests via CI (no race) (exports coverage)
test-ci-short Runs unit tests via CI (exports coverage)
test-no-lint Runs just tests
test-short Runs vet, lint and tests (excludes integration tests)
test-unit Runs tests and outputs coverage
uninstall Uninstall the application (and remove files)
update-linter Update the golangci-lint package (macOS only)
vet Run the Go vet application
```

</details>
Expand Down
60 changes: 29 additions & 31 deletions address.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,9 @@ import (
"errors"
"fmt"

"github.com/bitcoinsv/bsvd/bsvec"
"github.com/bitcoinsv/bsvd/chaincfg"
"github.com/bitcoinsv/bsvd/txscript"
"github.com/bitcoinsv/bsvutil"
"github.com/libsv/go-bk/bec"
"github.com/libsv/go-bk/crypto"
"github.com/libsv/go-bt/v2/bscript"
)

// A25 is a type for a 25 byte (not base58 encoded) bitcoin address.
Expand Down Expand Up @@ -89,13 +88,13 @@ func ValidA58(a58 []byte) (bool, error) {
return a.EmbeddedChecksum() == a.ComputeChecksum(), nil
}

// GetAddressFromPrivateKey takes a bsvec private key and returns a Bitcoin address
func GetAddressFromPrivateKey(privateKey *bsvec.PrivateKey, compressed bool) (string, error) {
// GetAddressFromPrivateKey takes a bec private key and returns a Bitcoin address
func GetAddressFromPrivateKey(privateKey *bec.PrivateKey, compressed bool) (string, error) {
address, err := GetAddressFromPubKey(privateKey.PubKey(), compressed)
if err != nil {
return "", err
}
return address.EncodeAddress(), nil
return address.AddressString, nil
}

// GetAddressFromPrivateKeyString takes a private key string and returns a Bitcoin address
Expand All @@ -104,32 +103,39 @@ func GetAddressFromPrivateKeyString(privateKey string, compressed bool) (string,
if err != nil {
return "", err
}
var address *bsvutil.LegacyAddressPubKeyHash
var address *bscript.Address
if address, err = GetAddressFromPubKey(rawKey.PubKey(), compressed); err != nil {
return "", err
}
return address.EncodeAddress(), nil
return address.AddressString, nil
}

// GetAddressFromPubKey gets a bsvutil.LegacyAddressPubKeyHash from a bsvec.PublicKey
func GetAddressFromPubKey(publicKey *bsvec.PublicKey, compressed bool) (*bsvutil.LegacyAddressPubKeyHash, error) {
// GetAddressFromPubKey gets a bscript.Address from a bec.PublicKey
func GetAddressFromPubKey(publicKey *bec.PublicKey, compressed bool) (*bscript.Address, error) {
if publicKey == nil {
return nil, fmt.Errorf("publicKey cannot be nil")
} else if publicKey.X == nil {
return nil, fmt.Errorf("publicKey.X cannot be nil")
}
var serializedPublicKey []byte
if compressed {
serializedPublicKey = publicKey.SerializeCompressed()
} else {
serializedPublicKey = publicKey.SerializeUncompressed()

if !compressed {
// go-bt/v2/bscript does not have a function that exports the uncompressed address
// https://github.com/libsv/go-bt/blob/master/bscript/address.go#L98
hash := crypto.Hash160(publicKey.SerialiseUncompressed())
bb := make([]byte, 1)
// nolint: makezero // we need to set up the array with 1
bb = append(bb, hash...)
return &bscript.Address{
AddressString: bscript.Base58EncodeMissingChecksum(bb),
PublicKeyHash: hex.EncodeToString(hash),
}, nil
}

return bsvutil.NewLegacyAddressPubKeyHash(bsvutil.Hash160(serializedPublicKey), &chaincfg.MainNetParams)
return bscript.NewAddressFromPublicKey(publicKey, true)
}

// GetAddressFromPubKeyString is a convenience function to use a hex string pubKey
func GetAddressFromPubKeyString(pubKey string, compressed bool) (*bsvutil.LegacyAddressPubKeyHash, error) {
func GetAddressFromPubKeyString(pubKey string, compressed bool) (*bscript.Address, error) {
rawPubKey, err := PubKeyFromString(pubKey)
if err != nil {
return nil, err
Expand All @@ -151,9 +157,10 @@ func GetAddressFromScript(script string) (string, error) {
return "", err
}

// Extract the components from the script
var addresses []bsvutil.Address
_, addresses, _, err = txscript.ExtractPkScriptAddrs(scriptBytes, &chaincfg.MainNetParams)
// Extract the addresses from the script
bScript := bscript.NewFromBytes(scriptBytes)
var addresses []string
addresses, err = bScript.Addresses()
if err != nil {
return "", err
}
Expand All @@ -165,15 +172,6 @@ func GetAddressFromScript(script string) (string, error) {
return "", fmt.Errorf("invalid output script, missing an address")
}

// Extract the address from the pubkey hash
var address *bsvutil.LegacyAddressPubKeyHash
if address, err = bsvutil.NewLegacyAddressPubKeyHash(
addresses[0].ScriptAddress(),
&chaincfg.MainNetParams,
); err != nil {
return "", err
}

// Use the encoded version of the address
return address.EncodeAddress(), nil
return addresses[0], nil
}
28 changes: 16 additions & 12 deletions address_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import (
"fmt"
"testing"

"github.com/bitcoinsv/bsvd/bsvec"
"github.com/libsv/go-bk/bec"
"github.com/stretchr/testify/assert"
)

Expand Down Expand Up @@ -97,7 +97,7 @@ func TestGetAddressFromPrivateKey(t *testing.T) {
// TestGetAddressFromPrivateKeyCompression will test the method GetAddressFromPrivateKey()
func TestGetAddressFromPrivateKeyCompression(t *testing.T) {

privateKey, err := bsvec.NewPrivateKey(bsvec.S256())
privateKey, err := bec.NewPrivateKey(bec.S256())
assert.NoError(t, err)

var addressUncompressed string
Expand All @@ -109,6 +109,10 @@ func TestGetAddressFromPrivateKeyCompression(t *testing.T) {
assert.NoError(t, err)

assert.NotEqual(t, addressCompressed, addressUncompressed)

addressCompressed, err = GetAddressFromPrivateKey(&bec.PrivateKey{}, true)
assert.Error(t, err)
assert.Equal(t, "", addressCompressed)
}

// ExampleGetAddressFromPrivateKey example using GetAddressFromPrivateKey()
Expand All @@ -131,7 +135,7 @@ func BenchmarkGetAddressFromPrivateKey(b *testing.B) {
}

// testGetPublicKeyFromPrivateKey is a helper method for tests
func testGetPublicKeyFromPrivateKey(privateKey string) *bsvec.PublicKey {
func testGetPublicKeyFromPrivateKey(privateKey string) *bec.PublicKey {
rawKey, err := PrivateKeyFromString(privateKey)
if err != nil {
return nil
Expand All @@ -144,18 +148,18 @@ func TestGetAddressFromPubKey(t *testing.T) {
t.Parallel()

var tests = []struct {
input *bsvec.PublicKey
input *bec.PublicKey
expectedAddress string
expectedNil bool
expectedError bool
}{
{&bsvec.PublicKey{}, "", true, true},
{&bec.PublicKey{}, "", true, true},
{testGetPublicKeyFromPrivateKey("54035dd4c7dda99ac473905a3d82f7864322b49bab1ff441cc457183b9bd8abd"), "1DfGxKmgL3ETwUdNnXLBueEvNpjcDGcKgK", false, false},
{testGetPublicKeyFromPrivateKey("000000"), "15wJjXvfQzo3SXqoWGbWZmNYND1Si4siqV", false, false},
{testGetPublicKeyFromPrivateKey("0"), "15wJjXvfQzo3SXqoWGbWZmNYND1Si4siqV", true, true},
}

// todo: add more error cases of invalid *bsvec.PublicKey
// todo: add more error cases of invalid *bec.PublicKey

for _, test := range tests {
if rawKey, err := GetAddressFromPubKey(test.input, true); err != nil && !test.expectedError {
Expand All @@ -166,8 +170,8 @@ func TestGetAddressFromPubKey(t *testing.T) {
t.Fatalf("%s Failed: [%v] inputted and was nil but not expected", t.Name(), test.input)
} else if rawKey != nil && test.expectedNil {
t.Fatalf("%s Failed: [%v] inputted and was NOT nil but expected to be nil", t.Name(), test.input)
} else if rawKey != nil && rawKey.EncodeAddress() != test.expectedAddress {
t.Fatalf("%s Failed: [%v] inputted [%s] expected but failed comparison of addresses, got: %s", t.Name(), test.input, test.expectedAddress, rawKey.EncodeAddress())
} else if rawKey != nil && rawKey.AddressString != test.expectedAddress {
t.Fatalf("%s Failed: [%v] inputted [%s] expected but failed comparison of addresses, got: %s", t.Name(), test.input, test.expectedAddress, rawKey.AddressString)
}
}
}
Expand All @@ -179,7 +183,7 @@ func ExampleGetAddressFromPubKey() {
fmt.Printf("error occurred: %s", err.Error())
return
}
fmt.Printf("address found: %s", rawAddress.EncodeAddress())
fmt.Printf("address found: %s", rawAddress.AddressString)
// Output:address found: 1DfGxKmgL3ETwUdNnXLBueEvNpjcDGcKgK
}

Expand Down Expand Up @@ -267,8 +271,8 @@ func TestGetAddressFromPubKeyString(t *testing.T) {
t.Fatalf("%s Failed: [%v] inputted and was nil but not expected", t.Name(), test.input)
} else if rawKey != nil && test.expectedNil {
t.Fatalf("%s Failed: [%v] inputted and was NOT nil but expected to be nil", t.Name(), test.input)
} else if rawKey != nil && rawKey.EncodeAddress() != test.expectedAddress {
t.Fatalf("%s Failed: [%v] inputted [%s] expected but failed comparison of addresses, got: %s", t.Name(), test.input, test.expectedAddress, rawKey.EncodeAddress())
} else if rawKey != nil && rawKey.AddressString != test.expectedAddress {
t.Fatalf("%s Failed: [%v] inputted [%s] expected but failed comparison of addresses, got: %s", t.Name(), test.input, test.expectedAddress, rawKey.AddressString)
}
}
}
Expand All @@ -280,7 +284,7 @@ func ExampleGetAddressFromPubKeyString() {
fmt.Printf("error occurred: %s", err.Error())
return
}
fmt.Printf("address found: %s", rawAddress.EncodeAddress())
fmt.Printf("address found: %s", rawAddress.AddressString)
// Output:address found: 17HeHWVDqDqexLJ31aG4qtVMoX8pKMGSuJ
}

Expand Down
26 changes: 13 additions & 13 deletions encryption.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@ package bitcoin
import (
"encoding/hex"

"github.com/bitcoinsv/bsvd/bsvec"
"github.com/libsv/go-bk/bec"
)

// EncryptWithPrivateKey will encrypt the data using a given private key
func EncryptWithPrivateKey(privateKey *bsvec.PrivateKey, data string) (string, error) {
func EncryptWithPrivateKey(privateKey *bec.PrivateKey, data string) (string, error) {

// Encrypt using bsvec
encryptedData, err := bsvec.Encrypt(privateKey.PubKey(), []byte(data))
// Encrypt using bec
encryptedData, err := bec.Encrypt(privateKey.PubKey(), []byte(data))
if err != nil {
return "", err
}
Expand All @@ -21,7 +21,7 @@ func EncryptWithPrivateKey(privateKey *bsvec.PrivateKey, data string) (string, e

// DecryptWithPrivateKey is a wrapper to decrypt the previously encrypted
// information, given a corresponding private key
func DecryptWithPrivateKey(privateKey *bsvec.PrivateKey, data string) (string, error) {
func DecryptWithPrivateKey(privateKey *bec.PrivateKey, data string) (string, error) {

// Decode the hex encoded string
rawData, err := hex.DecodeString(data)
Expand All @@ -31,7 +31,7 @@ func DecryptWithPrivateKey(privateKey *bsvec.PrivateKey, data string) (string, e

// Decrypt the data
var decrypted []byte
if decrypted, err = bsvec.Decrypt(privateKey, rawData); err != nil {
if decrypted, err = bec.Decrypt(privateKey, rawData); err != nil {
return "", err
}
return string(decrypted), nil
Expand All @@ -46,7 +46,7 @@ func EncryptWithPrivateKeyString(privateKey, data string) (string, error) {
return "", err
}

// Encrypt using bsvec
// Encrypt using bec
return EncryptWithPrivateKey(rawPrivateKey, data)
}

Expand All @@ -64,26 +64,26 @@ func DecryptWithPrivateKeyString(privateKey, data string) (string, error) {
}

// EncryptShared will encrypt data and provide shared keys for decryption
func EncryptShared(user1PrivateKey *bsvec.PrivateKey, user2PubKey *bsvec.PublicKey, data []byte) (
*bsvec.PrivateKey, *bsvec.PublicKey, []byte, error) {
func EncryptShared(user1PrivateKey *bec.PrivateKey, user2PubKey *bec.PublicKey, data []byte) (
*bec.PrivateKey, *bec.PublicKey, []byte, error) {

// Generate shared keys that can be decrypted by either user
sharedPrivKey, sharedPubKey := GenerateSharedKeyPair(user1PrivateKey, user2PubKey)

// Encrypt data with shared key
encryptedData, err := bsvec.Encrypt(sharedPubKey, data)
encryptedData, err := bec.Encrypt(sharedPubKey, data)
return sharedPrivKey, sharedPubKey, encryptedData, err
}

// EncryptSharedString will encrypt a string to a hex encoded encrypted payload, and provide shared keys for decryption
func EncryptSharedString(user1PrivateKey *bsvec.PrivateKey, user2PubKey *bsvec.PublicKey, data string) (
*bsvec.PrivateKey, *bsvec.PublicKey, string, error) {
func EncryptSharedString(user1PrivateKey *bec.PrivateKey, user2PubKey *bec.PublicKey, data string) (
*bec.PrivateKey, *bec.PublicKey, string, error) {

// Generate shared keys that can be decrypted by either user
sharedPrivKey, sharedPubKey := GenerateSharedKeyPair(user1PrivateKey, user2PubKey)

// Encrypt data with shared key
encryptedData, err := bsvec.Encrypt(sharedPubKey, []byte(data))
encryptedData, err := bec.Encrypt(sharedPubKey, []byte(data))

return sharedPrivKey, sharedPubKey, hex.EncodeToString(encryptedData), err
}
Loading

0 comments on commit b97670d

Please sign in to comment.