From 38e9a07bc89da744efe4a7fc09c1391c1e15a845 Mon Sep 17 00:00:00 2001 From: mrz1836 Date: Wed, 30 Sep 2020 10:36:54 -0400 Subject: [PATCH 1/7] Added basic makefiles for go package --- .gitignore | 3 ++ .make/Makefile.common | 71 ++++++++++++++++++++++++++++++++++++++ .make/Makefile.go | 80 +++++++++++++++++++++++++++++++++++++++++++ Makefile | 28 +++++++++++++++ 4 files changed, 182 insertions(+) create mode 100644 .make/Makefile.common create mode 100644 .make/Makefile.go create mode 100644 Makefile diff --git a/.gitignore b/.gitignore index 66fd13c..76760de 100644 --- a/.gitignore +++ b/.gitignore @@ -13,3 +13,6 @@ # Dependency directories (remove the comment below to include it) # vendor/ + +# JetBeans +.idea diff --git a/.make/Makefile.common b/.make/Makefile.common new file mode 100644 index 0000000..7010728 --- /dev/null +++ b/.make/Makefile.common @@ -0,0 +1,71 @@ +## Default repository domain name +ifndef GIT_DOMAIN + override GIT_DOMAIN=github.com +endif + +## Set if defined (alias variable for ease of use) +ifdef branch + override REPO_BRANCH=$(branch) + export REPO_BRANCH +endif + +## Do we have git available? +HAS_GIT := $(shell command -v git 2> /dev/null) + +ifdef HAS_GIT + ## Do we have a repo? + HAS_REPO := $(shell git rev-parse --is-inside-work-tree 2> /dev/null) + ifdef HAS_REPO + ## Automatically detect the repo owner and repo name (for local use with Git) + REPO_NAME=$(shell basename "$(shell git rev-parse --show-toplevel 2> /dev/null)") + REPO_OWNER=$(shell git config --get remote.origin.url | sed 's/git@$(GIT_DOMAIN)://g' | sed 's/\/$(REPO_NAME).git//g') + VERSION_SHORT=$(shell git describe --tags --always --abbrev=0) + export REPO_NAME, REPO_OWNER, VERSION_SHORT + endif +endif + +## Set the distribution folder +ifndef DISTRIBUTIONS_DIR + override DISTRIBUTIONS_DIR=./dist +endif +export DISTRIBUTIONS_DIR + +help: ## Show this help message + @egrep -h '^(.+)\:\ ##\ (.+)' ${MAKEFILE_LIST} | column -t -c 2 -s ':#' + +release:: ## Full production release (creates release in Github) + @test $(github_token) + @export GITHUB_TOKEN=$(github_token) && goreleaser --rm-dist + +release-test: ## Full production test release (everything except deploy) + @goreleaser --skip-publish --rm-dist + +release-snap: ## Test the full release (build binaries) + @goreleaser --snapshot --skip-publish --rm-dist + +replace-version: ## Replaces the version in HTML/JS (pre-deploy) + @test $(version) + @test "$(path)" + @find $(path) -name "*.html" -type f -exec sed -i '' -e "s/{{version}}/$(version)/g" {} \; + @find $(path) -name "*.js" -type f -exec sed -i '' -e "s/{{version}}/$(version)/g" {} \; + +tag: ## Generate a new tag and push (tag version=0.0.0) + @test $(version) + @git tag -a v$(version) -m "Pending full release..." + @git push origin v$(version) + @git fetch --tags -f + +tag-remove: ## Remove a tag if found (tag-remove version=0.0.0) + @test $(version) + @git tag -d v$(version) + @git push --delete origin v$(version) + @git fetch --tags + +tag-update: ## Update an existing tag to current commit (tag-update version=0.0.0) + @test $(version) + @git push --force origin HEAD:refs/tags/v$(version) + @git fetch --tags -f + +update-releaser: ## Update the goreleaser application + @brew update + @brew upgrade goreleaser diff --git a/.make/Makefile.go b/.make/Makefile.go new file mode 100644 index 0000000..86fdde3 --- /dev/null +++ b/.make/Makefile.go @@ -0,0 +1,80 @@ +## Default to the repo name if empty +ifndef BINARY_NAME + override BINARY_NAME=app +endif + +## Define the binary name +ifdef CUSTOM_BINARY_NAME + override BINARY_NAME=$(CUSTOM_BINARY_NAME) +endif + +## Set the binary release names +DARWIN=$(BINARY_NAME)-darwin +LINUX=$(BINARY_NAME)-linux +WINDOWS=$(BINARY_NAME)-windows.exe + +.PHONY: test lint install + +bench: ## Run all benchmarks in the Go application + @go test -bench=. -benchmem + +build-go: ## Build the Go application (locally) + @go build -o bin/$(BINARY_NAME) + +clean-mods: ## Remove all the Go mod cache + @go clean -modcache + +coverage: ## Shows the test coverage + @go test -coverprofile=coverage.out ./... && go tool cover -func=coverage.out + +godocs: ## Sync the latest tag with GoDocs + @test $(GIT_DOMAIN) + @test $(REPO_OWNER) + @test $(REPO_NAME) + @test $(VERSION_SHORT) + @curl https://proxy.golang.org/$(GIT_DOMAIN)/$(REPO_OWNER)/$(REPO_NAME)/@v/$(VERSION_SHORT).info + +install: ## Install the application + @go build -o $$GOPATH/bin/$(BINARY_NAME) + +install-go: ## Install the application (Using Native Go) + @go install $(GIT_DOMAIN)/$(REPO_OWNER)/$(REPO_NAME) + +lint: ## Run the Go lint application + @if [ "$(shell command -v golint)" = "" ]; then go get -u golang.org/x/lint/golint; fi + @golint + +test: ## Runs vet, lint and ALL tests + @$(MAKE) vet + @$(MAKE) lint + @go test ./... -v + +test-short: ## Runs vet, lint and tests (excludes integration tests) + @$(MAKE) vet + @$(MAKE) lint + @go test ./... -v -test.short + +test-travis: ## Runs all tests via Travis (also exports coverage) + @$(MAKE) vet + @$(MAKE) lint + @go test ./... -race -coverprofile=coverage.txt -covermode=atomic + +test-travis-short: ## Runs unit tests via Travis (also exports coverage) + @$(MAKE) vet + @$(MAKE) lint + @go test ./... -test.short -race -coverprofile=coverage.txt -covermode=atomic + +uninstall: ## Uninstall the application (and remove files) + @test $(BINARY_NAME) + @test $(GIT_DOMAIN) + @test $(REPO_OWNER) + @test $(REPO_NAME) + @go clean -i $(GIT_DOMAIN)/$(REPO_OWNER)/$(REPO_NAME) + @rm -rf $$GOPATH/src/$(GIT_DOMAIN)/$(REPO_OWNER)/$(REPO_NAME) + @rm -rf $$GOPATH/bin/$(BINARY_NAME) + +update: ## Update all project dependencies + @go get -u ./... && go mod tidy + +vet: ## Run the Go vet application + @go vet -v ./... \ No newline at end of file diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..9316e93 --- /dev/null +++ b/Makefile @@ -0,0 +1,28 @@ +# Common makefile commands & variables between projects +include .make/Makefile.common + +# Common Golang makefile commands & variables between projects +include .make/Makefile.go + +## Not defined? Use default repo name which is the application +ifeq ($(REPO_NAME),) + REPO_NAME="go-bitcoin" +endif + +## Not defined? Use default repo owner +ifeq ($(REPO_OWNER),) + REPO_OWNER="rohenaz" +endif + +.PHONY: clean + +all: ## Runs multiple commands + @$(MAKE) test + +clean: ## Remove previous builds and any test cache data + @go clean -cache -testcache -i -r + @test $(DISTRIBUTIONS_DIR) + @if [ -d $(DISTRIBUTIONS_DIR) ]; then rm -r $(DISTRIBUTIONS_DIR); fi + +release:: ## Runs common.release then runs godocs + @$(MAKE) godocs \ No newline at end of file From 970ddecfd02e25ef538fb7a3725f84a77e902f07 Mon Sep 17 00:00:00 2001 From: mrz1836 Date: Wed, 30 Sep 2020 10:37:02 -0400 Subject: [PATCH 2/7] Upgraded to go 1.15 --- go.mod | 4 ++-- go.sum | 5 +++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/go.mod b/go.mod index 8214012..3b30741 100644 --- a/go.mod +++ b/go.mod @@ -1,11 +1,11 @@ module github.com/rohenaz/go-bitcoin -go 1.14 +go 1.15 require ( github.com/bitcoinsv/bsvd v0.0.0-20190609155523-4c29707f7173 github.com/bitcoinsv/bsvutil v0.0.0-20181216182056-1d77cf353ea9 github.com/itchyny/base58-go v0.1.0 - github.com/piotrnar/gocoin v0.0.0-20200912093848-56d57d5b6be5 + github.com/piotrnar/gocoin v0.0.0-20200920172007-af9cf2799157 golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a ) diff --git a/go.sum b/go.sum index 4f54f48..ae193bf 100644 --- a/go.sum +++ b/go.sum @@ -2,12 +2,13 @@ github.com/bitcoinsv/bsvd v0.0.0-20190609155523-4c29707f7173 h1:2yTIV9u7H0BhRDGX github.com/bitcoinsv/bsvd v0.0.0-20190609155523-4c29707f7173/go.mod h1:BZ1UcC9+tmcDEcdVXgpt13hMczwJxWzpAn68wNs7zRA= github.com/bitcoinsv/bsvutil v0.0.0-20181216182056-1d77cf353ea9 h1:hFI8rT84FCA0FFy3cFrkW5Nz4FyNKlIdCvEvvTNySKg= github.com/bitcoinsv/bsvutil v0.0.0-20181216182056-1d77cf353ea9/go.mod h1:p44KuNKUH5BC8uX4ONEODaHUR4+ibC8todEAOGQEJAM= +github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/itchyny/base58-go v0.1.0 h1:zF5spLDo956exUAD17o+7GamZTRkXOZlqJjRciZwd1I= github.com/itchyny/base58-go v0.1.0/go.mod h1:SrMWPE3DFuJJp1M/RUhu4fccp/y9AlB8AL3o3duPToU= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= -github.com/piotrnar/gocoin v0.0.0-20200912093848-56d57d5b6be5 h1:7qMjDCz7USXw18S5feMCKjFtXTsv5yeK62TwFiP4nQE= -github.com/piotrnar/gocoin v0.0.0-20200912093848-56d57d5b6be5/go.mod h1:sW6i99ojgdRHcz53PCjyEeoTEDFh9dfP5iiEIiNfcaM= +github.com/piotrnar/gocoin v0.0.0-20200920172007-af9cf2799157 h1:evqZpI+lpcFQv7dEyquTJf5eyuuHJBtoRSq1d4nbUzk= +github.com/piotrnar/gocoin v0.0.0-20200920172007-af9cf2799157/go.mod h1:sW6i99ojgdRHcz53PCjyEeoTEDFh9dfP5iiEIiNfcaM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= From fef5af22c47b7fa4136ad444cbaf00408cba355d Mon Sep 17 00:00:00 2001 From: mrz1836 Date: Wed, 30 Sep 2020 10:37:14 -0400 Subject: [PATCH 3/7] Various cleanup, friendly names, etc --- address.go | 2 +- sign.go | 2 +- sign_test.go | 6 +- util.go | 1 + verify.go | 162 +++++++++++++++++++++++++++------------------------ 5 files changed, 92 insertions(+), 81 deletions(-) diff --git a/address.go b/address.go index ff3a229..a16528c 100644 --- a/address.go +++ b/address.go @@ -39,7 +39,7 @@ func (a *A25) EmbeddedChecksum() (c [4]byte) { } // Tmpl and Set58 are adapted from the C solution. -// Go has big integers but this techinique seems better. +// Go has big integers but this technique seems better. var tmpl = []byte("123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz") // Set58 takes a base58 encoded address and decodes it into the receiver. diff --git a/sign.go b/sign.go index 66a0fe6..8b03112 100644 --- a/sign.go +++ b/sign.go @@ -11,7 +11,7 @@ import ( func SignMessage(privKey string, message string) string { prefixBytes := []byte("Bitcoin Signed Message:\n") messageBytes := []byte(message) - bytes := []byte{} + var bytes []byte bytes = append(bytes, byte(len(prefixBytes))) bytes = append(bytes, prefixBytes...) bytes = append(bytes, byte(len(messageBytes))) diff --git a/sign_test.go b/sign_test.go index f43c351..a8eecb0 100644 --- a/sign_test.go +++ b/sign_test.go @@ -7,6 +7,7 @@ import ( // Identity Private Key const privKey = "E83385AF76B2B1997326B567461FB73DD9C27EAB9E1E86D26779F4650C5F2B75" +// TestSignMessage will test the method SignMessage() func TestSignMessage(t *testing.T) { // privKey string, message string, compress bool @@ -17,13 +18,14 @@ func TestSignMessage(t *testing.T) { } } +// TestVerifyMessage will test the method VerifyMessage() func TestVerifyMessage(t *testing.T) { var sig = "IBDscOd/Ov4yrd/YXantqajSAnW4fudpfr2KQy5GNo9pZybF12uNaal4KI822UpQLS/UJD+UK2SnNMn6Z3E4na8=" var address = "1FiyJnrgwBc3Ff83V1yRWAkmXBdGrDQnXQ" var data = "Testing!" - if !VerifyMessage(address, sig, data) { - t.Error("Failed to verify message") + if err := VerifyMessage(address, sig, data); err != nil { + t.Fatalf("failed to verify message: %s", err.Error()) } } diff --git a/util.go b/util.go index 52254d0..a3669b5 100644 --- a/util.go +++ b/util.go @@ -3,6 +3,7 @@ package bitcoin import "encoding/hex" // HexDecode returns a decoded hex string without handling errors +// todo: why ignore the error? (@mrz) func HexDecode(str string) []byte { b, _ := hex.DecodeString(str) return b diff --git a/verify.go b/verify.go index 9c86cf8..1921587 100644 --- a/verify.go +++ b/verify.go @@ -12,9 +12,9 @@ import ( ) func sha256d(body []byte) []byte { - msghash1 := sha256.Sum256([]byte(body)) - msghash2 := sha256.Sum256(msghash1[:]) - return msghash2[:] + msgHash1 := sha256.Sum256(body) + msgHash2 := sha256.Sum256(msgHash1[:]) + return msgHash2[:] } const ( @@ -23,60 +23,56 @@ const ( ) // VerifyMessage verifies a string and address against the provided signature and assumes Bitcoin Signed Message encoding -func VerifyMessage(address, signature, data string) (ok bool) { - addrs, err := sigmestoaddr(signature, data) +func VerifyMessage(address, signature, data string) error { + addresses, err := sigMessageToAddress(signature, data) if err != nil { - return + return err } - for _, addr2 := range addrs { + for _, addr2 := range addresses { if address == addr2 { - ok = true - return + return nil } } - return + return fmt.Errorf("address: %s not found", address) } -func messagehash(message, header string) (msghash2 []byte, err error) { - hlen := len(header) - if hlen >= 0xfd { - err = fmt.Errorf("long header is not supported") - return - } - mlen := len(message) - if mlen >= 0xfd { - err = fmt.Errorf("long message is not supported") - return - } - bitcoinmsg := string([]byte{byte(hlen)}) - bitcoinmsg += header - bitcoinmsg += string([]byte{byte(mlen)}) - bitcoinmsg += message - msghash2 = sha256d([]byte(bitcoinmsg)) - return +// messageHash will compute a hash for the given message & header +func messageHash(message, header string) ([]byte, error) { + headerLength := len(header) + if headerLength >= 0xfd { + return nil, fmt.Errorf("long header is not supported") + } + messageLength := len(message) + if messageLength >= 0xfd { + return nil, fmt.Errorf("long message is not supported") + } + bitcoinMsg := string([]byte{byte(headerLength)}) + bitcoinMsg += header + bitcoinMsg += string([]byte{byte(messageLength)}) + bitcoinMsg += message + return sha256d([]byte(bitcoinMsg)), nil } -func parseSignature(signature string) (sig secp256k1.Signature, recid int, - err error) { - sigraw, err2 := base64.StdEncoding.DecodeString(signature) - if err2 != nil { - err = err2 +// parseSignature will parse the given signature +func parseSignature(signature string) (sig secp256k1.Signature, recID int, err error) { + var sigRaw []byte + if sigRaw, err = base64.StdEncoding.DecodeString(signature); err != nil { return } - r0 := sigraw[0] - 27 - recid = int(r0 & 3) + r0 := sigRaw[0] - 27 + recID = int(r0 & 3) compressed := (r0 & 4) == 1 if compressed { err = fmt.Errorf("compressed type is not supported") return } - sig.R.SetBytes(sigraw[1 : 1+32]) - sig.S.SetBytes(sigraw[1+32 : 1+32+32]) + sig.R.SetBytes(sigRaw[1 : 1+32]) + sig.S.SetBytes(sigRaw[1+32 : 1+32+32]) return } -func pubtoaddr(pubkeyXy2 secp256k1.XY, compressed bool, - magic []byte) (bcpy []byte) { +// pubKeyToAddress will convert a pubkey to an address +func pubKeyToAddress(pubkeyXy2 secp256k1.XY, compressed bool, magic []byte) (bcpy []byte) { size := 65 if compressed { size = 33 @@ -97,16 +93,16 @@ func pubtoaddr(pubkeyXy2 secp256k1.XY, compressed bool, return } -func addrToStr(bcpy []byte) (s string, err error) { +// addressToString will convert a raw address to a string version +func addressToString(bcpy []byte) (s string, err error) { z := new(big.Int) z.SetBytes(bcpy) enc := base58.BitcoinEncoding - var encdd []byte - encdd, err = enc.Encode([]byte(z.String())) - if err != nil { + var encodeResults []byte + if encodeResults, err = enc.Encode([]byte(z.String())); err != nil { return } - s = string(encdd) + s = string(encodeResults) for _, v := range bcpy { if v != 0 { break @@ -120,23 +116,22 @@ func addrToStr(bcpy []byte) (s string, err error) { // And modified for local package. // License is: // https://github.com/piotrnar/gocoin/blob/master/lib/secp256k1/COPYING -func getBin(num *secp256k1.Number, le int) []byte { +func getBin(num *secp256k1.Number, le int) ([]byte, error) { bts := num.Bytes() if len(bts) > le { - panic("buffer too small") + return nil, fmt.Errorf("buffer too small") } if len(bts) == le { - return bts + return bts, nil } - return append(make([]byte, le-len(bts)), bts...) + return append(make([]byte, le-len(bts)), bts...), nil } // This function is copied from "piotrnar/gocoin/lib/secp256k1". // And modified for local package. // License is: // https://github.com/piotrnar/gocoin/blob/master/lib/secp256k1/COPYING -func recover(sig *secp256k1.Signature, pubkey *secp256k1.XY, - m *secp256k1.Number, recid int) (ret bool) { +func recoverSig(sig *secp256k1.Signature, pubkey *secp256k1.XY, m *secp256k1.Number, recID int) (bool, error) { var theCurveP secp256k1.Number theCurveP.SetBytes([]byte{ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, @@ -147,18 +142,23 @@ func recover(sig *secp256k1.Signature, pubkey *secp256k1.XY, var xj, qj secp256k1.XYZ rx.Set(&sig.R.Int) - if (recid & 2) != 0 { + if (recID & 2) != 0 { rx.Add(&rx.Int, &secp256k1.TheCurve.Order.Int) if rx.Cmp(&theCurveP.Int) >= 0 { - return false + return false, nil // todo: is this actually an error? } } - fx.SetB32(getBin(&rx, 32)) + bin, err := getBin(&rx, 32) + if err != nil { + return false, err + } + + fx.SetB32(bin) - X.SetXO(&fx, (recid&1) != 0) + X.SetXO(&fx, (recID&1) != 0) if !X.IsValid() { - return false + return false, nil // todo: is this actually an error? } xj.SetXY(&X) @@ -175,39 +175,47 @@ func recover(sig *secp256k1.Signature, pubkey *secp256k1.XY, xj.ECmult(&qj, &u2, &u1) pubkey.SetXYZ(&qj) - return true + return true, nil } -func sigmestoaddr(signature, message string) (addrs []string, err error) { - msghash2, err2 := messagehash(message, hBSV) - if err2 != nil { - err = err2 - return +// sigMessageToAddress will convert a signature & message to a list of addresses +func sigMessageToAddress(signature, message string) ([]string, error) { + + // Get message hash + msgHash, err := messageHash(message, hBSV) + if err != nil { + return nil, err } - sig, recid, err2 := parseSignature(signature) - if err2 != nil { - err = err2 - return + + // Parse the signature + var sig secp256k1.Signature + var recID int + sig, recID, err = parseSignature(signature) + if err != nil { + return nil, err } var msg secp256k1.Number - msg.SetBytes(msghash2) + msg.SetBytes(msgHash) var pubkeyXy2 secp256k1.XY - ret2 := recover(&sig, &pubkeyXy2, &msg, recid) - if !ret2 { - err = fmt.Errorf("recover pubkey failed") - return + var ret bool + ret, err = recoverSig(&sig, &pubkeyXy2, &msg, recID) + if err != nil { + return nil, err + } else if !ret { + return nil, fmt.Errorf("recover pubkey failed") } - addrs = make([]string, 2) + addresses := make([]string, 2) for i, compressed := range []bool{true, false} { - bcpy := pubtoaddr(pubkeyXy2, compressed, []byte{byte(0)}) - s, err2 := addrToStr(bcpy) - if err2 != nil { - err = err2 - return + bcpy := pubKeyToAddress(pubkeyXy2, compressed, []byte{byte(0)}) + + var addressString string + addressString, err = addressToString(bcpy) + if err != nil { + return nil, err } - addrs[i] = s + addresses[i] = addressString } - return + return addresses, nil } From dc8e6c0f040bd57bf361bdd13a6508a2e57bdc27 Mon Sep 17 00:00:00 2001 From: mrz1836 Date: Wed, 30 Sep 2020 10:43:32 -0400 Subject: [PATCH 4/7] Added standard repo files --- .goreleaser.yml | 27 ++++++++++++++++++++++++ .travis.yml | 29 ++++++++++++++++++++++++++ CODE_OF_CONDUCT.md | 52 ++++++++++++++++++++++++++++++++++++++++++++++ CODE_STANDARDS.md | 37 +++++++++++++++++++++++++++++++++ CONTRIBUTING.md | 18 ++++++++++++++++ LICENSE | 21 +++++++++++++++++++ 6 files changed, 184 insertions(+) create mode 100644 .goreleaser.yml create mode 100644 .travis.yml create mode 100644 CODE_OF_CONDUCT.md create mode 100644 CODE_STANDARDS.md create mode 100644 CONTRIBUTING.md create mode 100644 LICENSE diff --git a/.goreleaser.yml b/.goreleaser.yml new file mode 100644 index 0000000..7580a49 --- /dev/null +++ b/.goreleaser.yml @@ -0,0 +1,27 @@ +# Make sure to check the documentation at http://goreleaser.com +# --------------------------- +# GENERAL +# --------------------------- +before: + hooks: + - make all +snapshot: + name_template: "{{ .Tag }}" +changelog: + sort: asc + filters: + exclude: + - '^.github:' + - '^test:' + +# --------------------------- +# BUILDER +# --------------------------- +build: + skip: true +# --------------------------- +# Github Release +# --------------------------- +release: + prerelease: true + name_template: "Release v{{.Version}}" \ No newline at end of file diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..abd6f1c --- /dev/null +++ b/.travis.yml @@ -0,0 +1,29 @@ +# Fast runner (trick from @y0ssar1an) (out-dated) +sudo: false + +# Language of deployment +language: go + +# Version +go: + - 1.15.x + +# Environment variables +env: + - GO111MODULE=on + +# Only clone the most recent commit +git: + depth: 1 + +# Notifications off +notifications: + email: false + +# Run all scripts +script: + - make test-travis + +# After build success +after_success: + - bash <(curl -s https://codecov.io/bash) \ No newline at end of file diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..be4bcd0 --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,52 @@ +# Code of Merit + +1. The project creators, lead developers, core team, constitute +the managing members of the project and have final say in every decision +of the project, technical or otherwise, including overruling previous decisions. +There are no limitations to this decisional power. + +2. Contributions are an expected result of your membership on the project. +Don't expect others to do your work or help you with your work forever. + +3. All members have the same opportunities to seek any challenge they want +within the project. + +4. Authority or position in the project will be proportional +to the accrued contribution. Seniority must be earned. + +5. Software is evolutive: the better implementations must supersede lesser +implementations. Technical advantage is the primary evaluation metric. + +6. This is a space for technical prowess; topics outside of the project +will not be tolerated. + +7. Non technical conflicts will be discussed in a separate space. Disruption +of the project will not be allowed. + +8. Individual characteristics, including but not limited to, +body, sex, sexual preference, race, language, religion, nationality, +or political preferences are irrelevant in the scope of the project and +will not be taken into account concerning your value or that of your contribution +to the project. + +9. Discuss or debate the idea, not the person. + +10. There is no room for ambiguity: Ambiguity will be met with questioning; +further ambiguity will be met with silence. It is the responsibility +of the originator to provide requested context. + +11. If something is illegal outside the scope of the project, it is illegal +in the scope of the project. This Code of Merit does not take precedence over +governing law. + +12. This Code of Merit governs the technical procedures of the project not the +activities outside of it. + +13. Participation on the project equates to agreement of this Code of Merit. + +14. No objectives beyond the stated objectives of this project are relevant +to the project. Any intent to deviate the project from its original purpose +of existence will constitute grounds for remedial action which may include +expulsion from the project. + +This document is the Code of Merit (`http://code-of-merit.org`), version 1.0. \ No newline at end of file diff --git a/CODE_STANDARDS.md b/CODE_STANDARDS.md new file mode 100644 index 0000000..6d34d16 --- /dev/null +++ b/CODE_STANDARDS.md @@ -0,0 +1,37 @@ +# Code Standards + +This project uses the following code standards and specifications from: +- [effective go](https://golang.org/doc/effective_go.html) +- [go tests](https://golang.org/pkg/testing/) +- [go examples](https://golang.org/pkg/testing/#hdr-Examples) +- [go benchmarks](https://golang.org/pkg/testing/#hdr-Benchmarks) +- [gofmt](https://golang.org/cmd/gofmt/) +- [golint](https://github.com/golang/lint) +- [godoc](https://godoc.org/golang.org/x/tools/cmd/godoc) +- [vet](https://golang.org/cmd/vet/) +- [report card](https://goreportcard.com/) + +### *effective go* standards +View the [effective go](https://golang.org/doc/effective_go.html) standards documentation. + +### *golint* specifications +The package [golint](https://github.com/golang/lint) differs from [gofmt](https://golang.org/cmd/gofmt/). The package [gofmt](https://golang.org/cmd/gofmt/) formats Go source code, whereas [golint](https://github.com/golang/lint) prints out style mistakes. The package [golint](https://github.com/golang/lint) differs from [vet](https://golang.org/cmd/vet/). The package [vet](https://golang.org/cmd/vet/) is concerned with correctness, whereas [golint](https://github.com/golang/lint) is concerned with coding style. The package [golint](https://github.com/golang/lint) is in use at Google, and it seeks to match the accepted style of the open source [Go project](https://golang.org/). + +How to install [golint](https://github.com/golang/lint): +```shell script +go get -u golang.org/x/lint/golint +cd ../go-bitcoin +golint +``` + +### *go vet* specifications +[Vet](https://golang.org/cmd/vet/) examines Go source code and reports suspicious constructs. [Vet](https://golang.org/cmd/vet/) uses heuristics that do not guarantee all reports are genuine problems, but it can find errors not caught by the compilers. + +How to run [vet](https://golang.org/cmd/vet/): +```shell script +cd ../go-bitcoin +go vet -v +``` + +### *godoc* specifications +All code is written with documentation in mind. Follow the best practices with naming, examples and function descriptions. \ No newline at end of file diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..7c5276b --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,18 @@ +# How to contribute + +Please send a GitHub Pull Request to with a clear list of what you've done (read more about [pull requests](http://help.github.com/pull-requests/)). The more tests the merrier. Please follow the coding conventions (below) and make sure all of your commits are atomic (one feature per commit). + +## Testing + +All tests follow the standard Go testing pattern. +- [Go Tests](https://golang.org/pkg/testing/) +- [Go Examples](https://golang.org/pkg/testing/#hdr-Examples) +- [Go Benchmarks](https://golang.org/pkg/testing/#hdr-Benchmarks) + +## Coding conventions + +This project follows [effective Go standards](https://golang.org/doc/effective_go.html) and uses additional convention tools: +- [godoc](https://godoc.org/golang.org/x/tools/cmd/godoc) +- [golint](https://github.com/golang/lint) +- [vet](https://golang.org/cmd/vet/) +- [GoReportCard.com](https://goreportcard.com/report/github.com/rohenaz/go-bitcoin) \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..9709db4 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2020 @rohenaz + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file From ac32969463280f8fcacbb8f2f9454f299bbcd9a7 Mon Sep 17 00:00:00 2001 From: mrz1836 Date: Wed, 30 Sep 2020 10:43:41 -0400 Subject: [PATCH 5/7] Minor renames for consistency --- privateKey.go => private_key.go | 0 verify.go | 18 +++++++++--------- 2 files changed, 9 insertions(+), 9 deletions(-) rename privateKey.go => private_key.go (100%) diff --git a/privateKey.go b/private_key.go similarity index 100% rename from privateKey.go rename to private_key.go diff --git a/verify.go b/verify.go index 1921587..a79101d 100644 --- a/verify.go +++ b/verify.go @@ -72,7 +72,7 @@ func parseSignature(signature string) (sig secp256k1.Signature, recID int, err e } // pubKeyToAddress will convert a pubkey to an address -func pubKeyToAddress(pubkeyXy2 secp256k1.XY, compressed bool, magic []byte) (bcpy []byte) { +func pubKeyToAddress(pubkeyXy2 secp256k1.XY, compressed bool, magic []byte) (byteCopy []byte) { size := 65 if compressed { size = 33 @@ -87,23 +87,23 @@ func pubKeyToAddress(pubkeyXy2 secp256k1.XY, compressed bool, magic []byte) (bcp ripemd160H.Reset() ripemd160H.Write(pubHash1) pubHash2 := ripemd160H.Sum(nil) - bcpy = append(magic, pubHash2...) - hash2 := sha256d(bcpy) - bcpy = append(bcpy, hash2[0:4]...) + byteCopy = append(magic, pubHash2...) + hash2 := sha256d(byteCopy) + byteCopy = append(byteCopy, hash2[0:4]...) return } // addressToString will convert a raw address to a string version -func addressToString(bcpy []byte) (s string, err error) { +func addressToString(byteCopy []byte) (s string, err error) { z := new(big.Int) - z.SetBytes(bcpy) + z.SetBytes(byteCopy) enc := base58.BitcoinEncoding var encodeResults []byte if encodeResults, err = enc.Encode([]byte(z.String())); err != nil { return } s = string(encodeResults) - for _, v := range bcpy { + for _, v := range byteCopy { if v != 0 { break } @@ -208,10 +208,10 @@ func sigMessageToAddress(signature, message string) ([]string, error) { addresses := make([]string, 2) for i, compressed := range []bool{true, false} { - bcpy := pubKeyToAddress(pubkeyXy2, compressed, []byte{byte(0)}) + byteCopy := pubKeyToAddress(pubkeyXy2, compressed, []byte{byte(0)}) var addressString string - addressString, err = addressToString(bcpy) + addressString, err = addressToString(byteCopy) if err != nil { return nil, err } From 150b46f33af8b9c05e556f5b3d882a602db64add Mon Sep 17 00:00:00 2001 From: mrz1836 Date: Wed, 30 Sep 2020 10:44:49 -0400 Subject: [PATCH 6/7] Added basic github template files --- .github/FUNDING.yml | 4 ++++ .github/IMAGES/github-share-image.png | Bin 0 -> 16481 bytes .github/ISSUE_TEMPLATE/bug_report.md | 23 ++++++++++++++++++++++ .github/ISSUE_TEMPLATE/feature_request.md | 19 ++++++++++++++++++ .github/ISSUE_TEMPLATE/question.md | 13 ++++++++++++ .github/PULL_REQUEST_TEMPLATE/general.md | 7 +++++++ 6 files changed, 66 insertions(+) create mode 100644 .github/FUNDING.yml create mode 100644 .github/IMAGES/github-share-image.png create mode 100755 .github/ISSUE_TEMPLATE/bug_report.md create mode 100755 .github/ISSUE_TEMPLATE/feature_request.md create mode 100755 .github/ISSUE_TEMPLATE/question.md create mode 100755 .github/PULL_REQUEST_TEMPLATE/general.md diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 0000000..4b82d51 --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1,4 @@ +# These are supported funding model platforms + +github: rohenaz +custom: https://gobitcoinsv.com/?tab=tips&af=go-bitcoin \ No newline at end of file diff --git a/.github/IMAGES/github-share-image.png b/.github/IMAGES/github-share-image.png new file mode 100644 index 0000000000000000000000000000000000000000..aacc03506bf298d0bb6e9be768c5a992a59f4f1a GIT binary patch literal 16481 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 Leae=F^#lG3HQydx literal 0 HcmV?d00001 diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100755 index 0000000..460480d --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,23 @@ +--- +name: Bug report +about: Create a report to help us improve this project +labels: bug-p3 +assignees: mrz1836 + +--- + +**Describe the bug** +A clear and concise description of what the bug is. + +**To Reproduce** +Steps to reproduce the behavior: +1. Go to '...' +2. Click on '....' +3. Scroll down to '....' +4. See error + +**Expected behavior** +A clear and concise description of what you expected to happen. + +**Additional context** +Add any other context about the problem here. diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100755 index 0000000..cb3fd96 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,19 @@ +--- +name: Feature request +about: Suggest an idea for this project +labels: idea +assignees: mrz1836 + +--- + +**Is your feature request related to a problem? Please describe.** +A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] + +**Describe the solution you'd like** +A clear and concise description of what you want to happen. + +**Describe alternatives you've considered** +A clear and concise description of any alternative solutions or features you've considered. + +**Additional context** +Add any other context or screenshots about the feature request here. diff --git a/.github/ISSUE_TEMPLATE/question.md b/.github/ISSUE_TEMPLATE/question.md new file mode 100755 index 0000000..c7f749a --- /dev/null +++ b/.github/ISSUE_TEMPLATE/question.md @@ -0,0 +1,13 @@ +--- +name: Question +about: 'General template for a question ' +labels: question +assignees: mrz1836 + +--- + +**What's your question?** +A clear and concise question using references to specific regions of code if applicable. + +**Additional context** +Add any other context or information. diff --git a/.github/PULL_REQUEST_TEMPLATE/general.md b/.github/PULL_REQUEST_TEMPLATE/general.md new file mode 100755 index 0000000..4030f6f --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE/general.md @@ -0,0 +1,7 @@ +Fixes # + +## Proposed Changes + + - + - + - From 6daf27c92cbe2f39d3ac93924f7328647a0f1718 Mon Sep 17 00:00:00 2001 From: mrz1836 Date: Wed, 30 Sep 2020 11:02:10 -0400 Subject: [PATCH 7/7] Added some basic tests for ValidA58 --- address.go | 21 +++++++++++-------- address_test.go | 55 +++++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 61 insertions(+), 15 deletions(-) diff --git a/address.go b/address.go index a16528c..d1b29cb 100644 --- a/address.go +++ b/address.go @@ -69,19 +69,22 @@ func (a *A25) Set58(s []byte) error { func (a *A25) ComputeChecksum() (c [4]byte) { copy(c[:], a.doubleSHA256()) return -} /* {{header|Go}} */ +} -// AddressFromPrivKey takes a private key string and returns a Bitcoin address -func AddressFromPrivKey(privKey string) string { - pubKey := PrivateKey(privKey).PubKey() - return Address(pubKey).EncodeAddress() +// AddressFromPrivateKey takes a private key string and returns a Bitcoin address +func AddressFromPrivateKey(privateKey string) (string, error) { + pubKey := PrivateKey(privateKey).PubKey() + address, err := Address(pubKey) + if err != nil { + return "", err + } + return address.EncodeAddress(), nil } // Address gets a bsvutil.LegacyAddressPubKeyHash -func Address(publicKey *bsvec.PublicKey) (address *bsvutil.LegacyAddressPubKeyHash) { +func Address(publicKey *bsvec.PublicKey) (*bsvutil.LegacyAddressPubKeyHash, error) { publicKeyHash := bsvutil.Hash160(publicKey.SerializeCompressed()) - address, _ = bsvutil.NewLegacyAddressPubKeyHash(publicKeyHash, &chaincfg.MainNetParams) - return + return bsvutil.NewLegacyAddressPubKeyHash(publicKeyHash, &chaincfg.MainNetParams) } // ValidA58 validates a base58 encoded bitcoin address. An address is valid @@ -89,7 +92,7 @@ func Address(publicKey *bsvec.PublicKey) (address *bsvutil.LegacyAddressPubKeyHa // and the checksum validates. Return value ok will be true for valid // addresses. If ok is false, the address is invalid and the error value // may indicate why. -func ValidA58(a58 []byte) (ok bool, err error) { +func ValidA58(a58 []byte) (bool, error) { var a A25 if err := a.Set58(a58); err != nil { return false, err diff --git a/address_test.go b/address_test.go index 08198bf..5b5225d 100644 --- a/address_test.go +++ b/address_test.go @@ -1,17 +1,60 @@ package bitcoin import ( + "fmt" "testing" ) -// Test address -const address = "1KCEAmVS6FFggtc7W9as7sEENvjt7DqMi2" - +// TestValidA58 will test the method ValidA58() func TestValidA58(t *testing.T) { - valid, err := ValidA58([]byte(address)) + t.Parallel() + + // Create the list of tests + var tests = []struct { + input string + expectedValid bool + expectedError bool + }{ + {"1KCEAmVS6FFggtc7W9as7sEENvjt7DqMi2", true, false}, + {"1KCEAmVS6FFggtc7W9as7sEENvjt7DqMi", false, false}, + {"1KCEAmV", false, false}, + {"", false, false}, + {"0", false, true}, + } + + // Run tests + for _, test := range tests { + if valid, err := ValidA58([]byte(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 valid && !test.expectedValid { + t.Errorf("%s Failed: [%s] inputted and was valid but should NOT be valid", t.Name(), test.input) + } else if !valid && test.expectedValid { + t.Errorf("%s Failed: [%s] inputted and was invalid but should be valid", t.Name(), test.input) + } + } +} + +// ExampleValidA58 example using ValidA58() +func ExampleValidA58() { + valid, err := ValidA58([]byte("1KCEAmVS6FFggtc7W9as7sEENvjt7DqMi2")) + if err != nil { + fmt.Printf("error occurred: %s", err.Error()) + return + } else if !valid { + fmt.Printf("address is not valid: %s", "1KCEAmVS6FFggtc7W9as7sEENvjt7DqMi2") + return + } else { + fmt.Printf("address is valid!") + } + // Output:address is valid! +} - if !valid { - t.Error("Failed to validate address", err) +// BenchmarkValidA58 benchmarks the method ValidA58() +func BenchmarkValidA58(b *testing.B) { + for i := 0; i < b.N; i++ { + _, _ = ValidA58([]byte("1KCEAmVS6FFggtc7W9as7sEENvjt7DqMi2")) } }