Skip to content

Commit

Permalink
Merge pull request #4 from 01node/feat/ecsda
Browse files Browse the repository at this point in the history
Add ecsda encryption and Berachain
  • Loading branch information
micovi committed Jan 22, 2024
2 parents 24a490a + 66b67c9 commit 18719d5
Show file tree
Hide file tree
Showing 13 changed files with 711 additions and 166 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
./vanity-forge
dist/
vanity-forge
68 changes: 68 additions & 0 deletions constants.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package main

type Encryption int64

const (
Undefined Encryption = iota
Secp256k1
Ethsecp256k1
ECSDA
)

type chain struct {
Name string
Prefix string
PrefixFull string
Encryption
}

type settings struct {
SelectedChain chain // chain selector string or nil
MatcherMode string // starts-with, ends-with, contains
SearchString string // search string
NumAccounts string // number of accounts to generate
RequiredLetters int // number of letters to generate
RequiredDigits int // number of digits to generate
}

type walletgenerator struct {
GenerateWallet func() wallet
}

type matcher struct {
Mode string
SearchString string
Chain chain
RequiredLetters int
RequiredDigits int
}

var (
AvailableChains = []chain{
{
Name: "celestia",
Prefix: "celestia",
PrefixFull: "celestia1",
Encryption: Secp256k1,
},
{
Name: "cosmos",
Prefix: "cosmos",
PrefixFull: "cosmos1",
Encryption: Secp256k1,
},
{
Name: "dydx",
Prefix: "dydx",
PrefixFull: "dydx1",
Encryption: Secp256k1,
},
{
Name: "berachain",
Prefix: "0x",
PrefixFull: "0x",
Encryption: ECSDA,
},
}
MatcherModes = []string{"contains", "starts-with", "ends-with", "regex"}
)
109 changes: 109 additions & 0 deletions ecsda.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
package main

import (
"crypto/ecdsa"
"log"
"strings"

"github.com/ethereum/go-ethereum/crypto"
)

type ecsdaWallet struct {
Chain chain
}

// On Ethereum and other networks compatible with the Ethereum Virtual Machine (EVM), public addresses all share the same format: they begin with 0x, and are followed by 40 alphanumeric characters (numerals and letters), adding up to 42 characters in total. They're also not case sensitive.

// This address is a number, even though it also includes alphabetical characters. This is because the hexadecimal (base 16) system used to generate the address doesn't just use numerals, like our ten-digit decimal system. Instead, the hexadecimal system uses the numerals 0-9 and the letters A-F. This means it has 16 characters at its disposal, hence the name base 16. In computer science and many programming languages, the 0x prefix is used at the start of all hex numbers, as they are known, to differentiate them from decimal values.

// bech16digits is a constant string representing the valid characters in a Bech16 encoding.
const bech16digits = "0123456789"

// bech16letters represents the valid characters for a Bech16 encoding.
const bech16letters = "abcdefABCDEF"

// bech16chars is a constant string that represents the characters used in the bech16 encoding scheme, which includes both digits and letters.
const bech16chars = bech16digits + bech16letters

// bech16Only checks if the given string contains only characters from the bech16 character set.
func (w ecsdaWallet) bech16Only(s string) bool {
return w.countUnionChars(s, bech16chars) == len(s)
}

// countUnionChars counts the number of characters in the input string 's' that are present in the 'letterSet'.
// It returns the count of such characters.
func (w ecsdaWallet) countUnionChars(s string, letterSet string) int {
count := 0
for _, char := range s {
if strings.Contains(letterSet, string(char)) {
count++
}
}
return count
}

// CheckRequiredDigits checks if the given candidate string has the required number of digits.
// It counts the number of union characters between the candidate string and the bech16digits string.
// If the count is less than the required number, it returns false; otherwise, it returns true.
func (w ecsdaWallet) CheckRequiredDigits(candidate string, required int) bool {
if w.countUnionChars(candidate, bech16digits) < required {
return false
}

return true
}

// CheckRequiredLetters checks if a candidate string contains the required number of union characters.
// It returns true if the candidate string meets the requirement, otherwise false.
func (w ecsdaWallet) CheckRequiredLetters(candidate string, required int) bool {
if w.countUnionChars(candidate, bech16letters) < required {
return false
}

return true
}

// ValidateInput validates the input string based on the specified criteria.
// It checks if the input string contains bech16 incompatible characters,
// if it exceeds the maximum length of 40 characters,
// and if the required number of letters and digits are non-negative and do not exceed 40.
// It returns a slice of error messages indicating the validation errors, if any.
func (w ecsdaWallet) ValidateInput(SearchString string, RequiredLetters int, RequiredDigits int) []string {
var errs []string
if !w.bech16Only(SearchString) {
errs = append(errs, "ERROR: "+SearchString+" contains bech16 incompatible characters")
}
if len(SearchString) > 40 {
errs = append(errs, "ERROR: "+SearchString+" is too long. Must be max 40 characters.")
}
if RequiredDigits < 0 || RequiredLetters < 0 {
errs = append(errs, "ERROR: Can't require negative amount of characters.")
}
if RequiredDigits+RequiredLetters > 40 {
errs = append(errs, "ERROR: Can't require more than 40 characters.")
}
return errs
}

// GenerateWallet generates a new wallet by generating a private key and deriving the corresponding public key and address.
// It returns a wallet struct containing the address, public key, and private key bytes.
func (w ecsdaWallet) GenerateWallet() wallet {
privateKey, err := crypto.GenerateKey()
if err != nil {
log.Fatal(err)
}

privateKeyBytes := crypto.FromECDSA(privateKey)

publicKey := privateKey.Public()
publicKeyECDSA, ok := publicKey.(*ecdsa.PublicKey)
if !ok {
log.Fatal("cannot assert type: publicKey is not of type *ecdsa.PublicKey")
}

publicKeyBytes := crypto.FromECDSAPub(publicKeyECDSA)

address := crypto.PubkeyToAddress(*publicKeyECDSA).Hex()

return wallet{address, publicKeyBytes, privateKeyBytes}
}
146 changes: 146 additions & 0 deletions ecsda_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
package main

import (
"testing"

"github.com/stretchr/testify/assert"
)

func TestEcsdaWallet_GenerateWallet(t *testing.T) {
wallet := ecsdaWallet{}
w := wallet.GenerateWallet()
assert.NotEmpty(t, w.Address)
assert.NotNil(t, w.PublicKey)
assert.NotNil(t, w.PrivateKey)
}
func TestEcsdaWallet_CountUnionChars(t *testing.T) {
wallet := ecsdaWallet{}

// Test case 1: Counting union characters in a string with valid letter set
s1 := "abcdef123456"
letterSet1 := "abc123"
expectedCount1 := 6
assert.Equal(t, expectedCount1, wallet.countUnionChars(s1, letterSet1), "Expected count of 6 for valid letter set")

// Test case 2: Counting union characters in a string with empty letter set
s2 := "abcdef123456"
letterSet2 := ""
expectedCount2 := 0
assert.Equal(t, expectedCount2, wallet.countUnionChars(s2, letterSet2), "Expected count of 0 for empty letter set")

// Test case 3: Counting union characters in an empty string with valid letter set
s3 := ""
letterSet3 := "abc123"
expectedCount3 := 0
assert.Equal(t, expectedCount3, wallet.countUnionChars(s3, letterSet3), "Expected count of 0 for empty string")

// Test case 4: Counting union characters in a string with invalid letter set
s4 := "abcdef123456"
letterSet4 := "!@#$%"
expectedCount4 := 0
assert.Equal(t, expectedCount4, wallet.countUnionChars(s4, letterSet4), "Expected count of 0 for invalid letter set")
}
func TestEcsdaWallet_Bech16Only(t *testing.T) {
wallet := ecsdaWallet{}

// Test case 1: All characters are valid bech16 characters
s1 := "abcdef123456"
assert.True(t, wallet.bech16Only(s1), "Expected true for valid bech16 characters")

// Test case 2: Some characters are not valid bech16 characters
s2 := "abcde!@#$%"
assert.False(t, wallet.bech16Only(s2), "Expected false for invalid bech16 characters")

// Test case 3: Empty string
s3 := ""
assert.True(t, wallet.bech16Only(s3), "Expected true for empty string")

// Test case 4: String with valid bech16 characters and additional characters
s4 := "abcdef123456!"
assert.False(t, wallet.bech16Only(s4), "Expected false for string with additional characters")
}
func TestEcsdaWallet_CheckRequiredDigits(t *testing.T) {
wallet := ecsdaWallet{}

// Test case 1: Candidate string has less required digits
candidate1 := "abcdef123456"
required1 := 7
assert.False(t, wallet.CheckRequiredDigits(candidate1, required1), "Expected false for candidate string with less required digits")

// Test case 2: Candidate string has exact required digits
candidate2 := "abcdef123456"
required2 := 6
assert.True(t, wallet.CheckRequiredDigits(candidate2, required2), "Expected true for candidate string with exact required digits")

// Test case 3: Candidate string has more than required digits
candidate3 := "abcdef123456"
required3 := 5
assert.True(t, wallet.CheckRequiredDigits(candidate3, required3), "Expected true for candidate string with more than required digits")

// Test case 4: Empty candidate string
candidate4 := ""
required4 := 3
assert.False(t, wallet.CheckRequiredDigits(candidate4, required4), "Expected false for empty candidate string")
}
func TestEcsdaWallet_CheckRequiredLetters(t *testing.T) {
wallet := ecsdaWallet{}

// Test case 1: Candidate string has enough required letters
candidate1 := "abcdef123"
required1 := 5
assert.True(t, wallet.CheckRequiredLetters(candidate1, required1), "Expected true for candidate string with enough required letters")

// Test case 2: Candidate string does not have enough required letters
candidate2 := "abc123"
required2 := 10
assert.False(t, wallet.CheckRequiredLetters(candidate2, required2), "Expected false for candidate string without enough required letters")

// Test case 3: Candidate string is empty
candidate3 := ""
required3 := 5
assert.False(t, wallet.CheckRequiredLetters(candidate3, required3), "Expected false for empty candidate string")

// Test case 4: Required letters is 0
candidate4 := "abc123"
required4 := 0
assert.True(t, wallet.CheckRequiredLetters(candidate4, required4), "Expected true for required letters equal to 0")
}

func TestEcsdaWallet_ValidateInput(t *testing.T) {
wallet := ecsdaWallet{}

// Test case 1: Valid input
searchString1 := "abcdef123456"
requiredLetters1 := 6
requiredDigits1 := 6
expectedErrs1 := []string(nil)
assert.Equal(t, expectedErrs1, wallet.ValidateInput(searchString1, requiredLetters1, requiredDigits1), "Expected no errors for valid input")

// Test case 2: Invalid bech16 characters
searchString2 := "abcde!@#$%"
requiredLetters2 := 6
requiredDigits2 := 6
expectedErrs2 := []string{"ERROR: abcde!@#$% contains bech16 incompatible characters"}
assert.Equal(t, expectedErrs2, wallet.ValidateInput(searchString2, requiredLetters2, requiredDigits2), "Expected error for invalid bech16 characters")

// Test case 3: String too long
searchString3 := "abcdef123456abcdef123456abcdef123456abcdef1234567"
requiredLetters3 := 6
requiredDigits3 := 6
expectedErrs3 := []string{"ERROR: abcdef123456abcdef123456abcdef123456abcdef1234567 is too long. Must be max 40 characters."}
assert.Equal(t, expectedErrs3, wallet.ValidateInput(searchString3, requiredLetters3, requiredDigits3), "Expected error for string too long")

// Test case 4: Negative required characters
searchString4 := "abcdef123456"
requiredLetters4 := -1
requiredDigits4 := 6
expectedErrs4 := []string{"ERROR: Can't require negative amount of characters."}
assert.Equal(t, expectedErrs4, wallet.ValidateInput(searchString4, requiredLetters4, requiredDigits4), "Expected error for negative required characters")

// Test case 5: Required characters exceed string length
searchString5 := "abcdef123456abcdef123456abcdef123456abcdef123456abcdef123456abcdef123456"
requiredLetters5 := 10
requiredDigits5 := 10
expectedErrs5 := []string{"ERROR: abcdef123456abcdef123456abcdef123456abcdef123456abcdef123456abcdef123456 is too long. Must be max 40 characters."}
assert.Equal(t, expectedErrs5, wallet.ValidateInput(searchString5, requiredLetters5, requiredDigits5), "Expected error for required characters exceeding string length")
}
12 changes: 10 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ require (
github.com/charmbracelet/huh v0.2.3
github.com/charmbracelet/huh/spinner v0.0.0-20240108162426-58163e7b5b2f
github.com/cosmos/cosmos-sdk v0.50.3
github.com/ethereum/go-ethereum v1.13.10
github.com/spf13/pflag v1.0.5
github.com/stretchr/testify v1.8.4
github.com/tendermint/tendermint v0.35.9
golang.org/x/exp v0.0.0-20240112132812-db7319d0e0e3
)
Expand All @@ -19,15 +21,19 @@ require (
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
github.com/aymerick/douceur v0.2.0 // indirect
github.com/btcsuite/btcd v0.22.1 // indirect
github.com/btcsuite/btcd/btcec/v2 v2.3.2 // indirect
github.com/catppuccin/go v0.2.0 // indirect
github.com/charmbracelet/bubbles v0.17.1 // indirect
github.com/charmbracelet/bubbletea v0.25.0 // indirect
github.com/charmbracelet/glamour v0.6.0 // indirect
github.com/charmbracelet/lipgloss v0.9.1 // indirect
github.com/containerd/console v1.0.4-0.20230313162750-1ae8d489ac81 // indirect
github.com/cosmos/btcutil v1.0.5 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect
github.com/dlclark/regexp2 v1.10.0 // indirect
github.com/gorilla/css v1.0.0 // indirect
github.com/holiman/uint256 v1.2.4 // indirect
github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mattn/go-localereader v0.0.1 // indirect
Expand All @@ -39,14 +45,16 @@ require (
github.com/muesli/termenv v0.15.2 // indirect
github.com/olekukonko/tablewriter v0.0.5 // indirect
github.com/petermattis/goid v0.0.0-20230904192822-1876fd5063bc // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/rivo/uniseg v0.4.4 // indirect
github.com/sasha-s/go-deadlock v0.3.1 // indirect
github.com/yuin/goldmark v1.6.0 // indirect
github.com/yuin/goldmark-emoji v1.0.2 // indirect
golang.org/x/crypto v0.16.0 // indirect
golang.org/x/crypto v0.17.0 // indirect
golang.org/x/net v0.19.0 // indirect
golang.org/x/sync v0.4.0 // indirect
golang.org/x/sync v0.5.0 // indirect
golang.org/x/sys v0.15.0 // indirect
golang.org/x/term v0.15.0 // indirect
golang.org/x/text v0.14.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
Loading

0 comments on commit 18719d5

Please sign in to comment.