diff --git a/.github/workflows/php.yml b/.github/workflows/php.yml new file mode 100644 index 0000000..a8588b1 --- /dev/null +++ b/.github/workflows/php.yml @@ -0,0 +1,29 @@ +name: Base58 + +on: + push: + branches: [main, goodsprings] + pull_request: + branches: [main] + +jobs: + build: + runs-on: ubuntu-latest + strategy: + matrix: + php-version: [8.1, 8.2, 8.3, 8.4, 8.5] + + steps: + - name: Checkout repository + uses: actions/checkout@v3 + + - name: Set up PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php-version }} + + - name: Install Composer dependencies + run: composer install --no-progress --prefer-dist + + - name: Run PHPUnit + run: bin/phpunit --no-coverage \ No newline at end of file diff --git a/.gitignore b/.gitignore index b2df07b..955fe35 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ /vendor/ +/coverage/ /bin/ composer.lock diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 4afc57a..0000000 --- a/.travis.yml +++ /dev/null @@ -1,17 +0,0 @@ -language: php - -before_script: - - composer install - -php: - - 5.3 - - 5.4 - - 5.5 - - 5.6 - - 7 - - 7.1 - - 7.2 - - 7.3 - - hhvm - -script: bin/phpunit diff --git a/benchmarks/Base16Event.php b/benchmarks/Base16Event.php deleted file mode 100644 index f3ec003..0000000 --- a/benchmarks/Base16Event.php +++ /dev/null @@ -1,24 +0,0 @@ -base58 = new Base58(null, new BCMathService()); - } - - /** - * @iterations 10000 - */ - public function encodeBase58() - { - $this->base58->encode('Hello World'); - } - - /** - * @iterations 10000 - */ - public function decodeBase58() - { - $this->base58->decode('JxF12TrwUP45BMd'); - } -} diff --git a/benchmarks/Base58GMPEvent.php b/benchmarks/Base58GMPEvent.php deleted file mode 100644 index d8a4d20..0000000 --- a/benchmarks/Base58GMPEvent.php +++ /dev/null @@ -1,33 +0,0 @@ -base58 = new Base58(null, new GMPService()); - } - - /** - * @iterations 10000 - */ - public function encodeBase58() - { - $this->base58->encode('Hello World'); - } - - /** - * @iterations 10000 - */ - public function decodeBase58() - { - $this->base58->decode('JxF12TrwUP45BMd'); - } -} diff --git a/benchmarks/Base64Event.php b/benchmarks/Base64Event.php deleted file mode 100644 index a558968..0000000 --- a/benchmarks/Base64Event.php +++ /dev/null @@ -1,24 +0,0 @@ -=8.1" + }, + "suggest": { + "ext-bcmath": "Required for BC Math support", + "ext-gmp": "Required for GMP support" + }, "require-dev": { - "phpunit/phpunit": "4.*", - "athletic/athletic": "~0.1" + "phpunit/phpunit": "10.*" }, "license": "MIT", "authors": [ @@ -17,8 +23,7 @@ }, "autoload": { "psr-4": { - "StephenHill\\": "src/", - "StephenHill\\Benchmarks\\": "benchmarks/" + "StephenHill\\": "src/" } } } \ No newline at end of file diff --git a/phpunit.xml b/phpunit.xml index 0636241..08c2af7 100644 --- a/phpunit.xml +++ b/phpunit.xml @@ -1,31 +1,28 @@ - - - - ./tests/ - - + - - - src - - vendor - - - - + + + tests + + + + + + src + + + + + + + + + \ No newline at end of file diff --git a/readme.md b/readme.md index 9723a91..94b1846 100644 --- a/readme.md +++ b/readme.md @@ -1,15 +1,15 @@ # Base58 Encoding and Decoding Library for PHP -[![Build Status](https://travis-ci.org/stephen-hill/base58php.png)](https://travis-ci.org/stephen-hill/base58php) [![Packagist Release](http://img.shields.io/packagist/v/stephenhill/base58.svg)](https://packagist.org/packages/stephenhill/base58) [![MIT License](http://img.shields.io/packagist/l/stephenhill/base58.svg)](https://github.com/stephen-hill/base58php/blob/master/license) -[![Flattr this](https://api.flattr.com/button/flattr-badge-large.png)](https://flattr.com/submit/auto?user_id=stephen-hill&url=https%3A%2F%2Fgithub.com%2Fstephen-hill%2Fbase58php) +[![Action Status](https://github.com/stephen-hill/base58php/actions/workflows/php.yml/badge.svg)](https://github.com/stephen-hill/base58php/actions/workflows/php.yml) ## Long Term Support Each major version of this library will be supported for 5 years after it's initial release. Support will be provided for security and bug fixes. -Version 1 will therefore be supported until the 11th September 2019. +- Version 2 will be supported until the 1st Janurary 2031. +- Version 1 support expired on the 11th September 2019. ## Background @@ -26,8 +26,8 @@ So I decided to create a library with the following goals: This library has the following requirements: -- PHP => 5.3 -- BC Math Extension +- PHP => 8.1 +- GMP or BC Math Extension ## Installation @@ -36,7 +36,7 @@ I recommend you install this library via Composer. ```json { "require": { - "stephenhill/base58": "~1.0" + "stephenhill/base58": "~2.0" } } ``` @@ -87,46 +87,6 @@ This library is tested using PHPUnit. $ bin/phpunit ``` -## Benchmarking - -You can benchmark this library using [Athletic](https://github.com/polyfractal/athletic). -The benchmarking suite also benchmarks PHP's built-in Base64 and Base16 encoding for comparison. - -```bash -$ bin/athletic -p benchmarks -``` - -Example output. - -``` -StephenHill\Benchmarks\Base16Event - Method Name Iterations Average Time Ops/second - ------------ ------------ -------------- ------------- - encodeBase16: [10,000 ] [0.0000010839939] [922,514.40637] - decodeBase16: [10,000 ] [0.0000011516809] [868,296.03561] - - -StephenHill\Benchmarks\Base58BCMathEvent - Method Name Iterations Average Time Ops/second - ------------ ------------ -------------- ------------- - encodeBase58: [10,000 ] [0.0001500048161] [6,666.45263] - decodeBase58: [10,000 ] [0.0001741812706] [5,741.14540] - - -StephenHill\Benchmarks\Base58GMPEvent - Method Name Iterations Average Time Ops/second - ------------ ------------ -------------- ------------- - encodeBase58: [10,000 ] [0.0001168665648] [8,556.76730] - decodeBase58: [10,000 ] [0.0001385705233] [7,216.54199] - - -StephenHill\Benchmarks\Base64Event - Method Name Iterations Average Time Ops/second - ------------ ------------ -------------- ------------- - encodeBase64: [10,000 ] [0.0000009050369] [1,104,927.29189] - decodeBase64: [10,000 ] [0.0000009787321] [1,021,730.04312] -``` - ## Contributing I welcome everyone to contribute to this library. Please see the Contributing document for details. @@ -143,3 +103,5 @@ Some of the unit tests were based on the following: - https://code.google.com/p/bitcoinj/source/browse/core/src/test/java/com/google/bitcoin/core/Base58Test.java - https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/fixtures/base58.json + +In no particular order, I would like to thank the following for pushing me to release a PHP 8 compatible version: @git-marijus, @VandalorumRex, @bacheson, @kalifg diff --git a/src/BCMathService.php b/src/BCMathService.php index 329e1ce..d424335 100644 --- a/src/BCMathService.php +++ b/src/BCMathService.php @@ -24,18 +24,13 @@ class BCMathService implements ServiceInterface * @param string $alphabet optional * @since v1.1.0 */ - public function __construct($alphabet = null) + public function __construct(?string $alphabet = null) { // Handle null alphabet if (is_null($alphabet) === true) { $alphabet = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'; } - // Type validation - if (is_string($alphabet) === false) { - throw new InvalidArgumentException('Argument $alphabet must be a string.'); - } - // The alphabet must contain 58 characters if (strlen($alphabet) !== 58) { throw new InvalidArgumentException('Argument $alphabet must contain 58 characters.'); @@ -51,13 +46,8 @@ public function __construct($alphabet = null) * @since Release v1.1.0 * @return string The Base58 encoded string. */ - public function encode($string) + public function encode(string $string) : string { - // Type validation - if (is_string($string) === false) { - throw new InvalidArgumentException('Argument $string must be a string.'); - } - // If the string is empty, then the encoded string is obviously empty if (strlen($string) === 0) { return ''; @@ -113,13 +103,8 @@ public function encode($string) * @since Release v1.1.0 * @return string Returns the decoded string. */ - public function decode($base58) + public function decode(string $base58) : string { - // Type Validation - if (is_string($base58) === false) { - throw new InvalidArgumentException('Argument $base58 must be a string.'); - } - // If the string is empty, then the decoded string is obviously empty if (strlen($base58) === 0) { return ''; diff --git a/src/Base58.php b/src/Base58.php index 75a2e0d..516e3c4 100644 --- a/src/Base58.php +++ b/src/Base58.php @@ -29,19 +29,14 @@ class Base58 * @since v1.1.0 Added the optional $service argument. */ public function __construct( - $alphabet = null, - ServiceInterface $service = null + ?string $alphabet = null, + ?ServiceInterface $service = null ) { // Handle null alphabet if (is_null($alphabet) === true) { $alphabet = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'; } - // Type validation - if (is_string($alphabet) === false) { - throw new InvalidArgumentException('Argument $alphabet must be a string.'); - } - // The alphabet must contain 58 characters if (strlen($alphabet) !== 58) { throw new InvalidArgumentException('Argument $alphabet must contain 58 characters.'); @@ -71,7 +66,7 @@ public function __construct( * @since v1.0.0 * @return string The Base58 encoded string. */ - public function encode($string) + public function encode(string $string) : string { return $this->service->encode($string); } @@ -83,7 +78,7 @@ public function encode($string) * @since v1.0.0 * @return string Returns the decoded string. */ - public function decode($base58) + public function decode(string $base58) : string { return $this->service->decode($base58); } diff --git a/src/GMPService.php b/src/GMPService.php index 0dde305..60a8d19 100644 --- a/src/GMPService.php +++ b/src/GMPService.php @@ -24,18 +24,13 @@ class GMPService implements ServiceInterface * @param string $alphabet optional * @since v1.1.0 */ - public function __construct($alphabet = null) + public function __construct(?string $alphabet = null) { // Handle null alphabet if (is_null($alphabet) === true) { $alphabet = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'; } - // Type validation - if (is_string($alphabet) === false) { - throw new InvalidArgumentException('Argument $alphabet must be a string.'); - } - // The alphabet must contain 58 characters if (strlen($alphabet) !== 58) { throw new InvalidArgumentException('Argument $alphabet must contain 58 characters.'); @@ -51,13 +46,8 @@ public function __construct($alphabet = null) * @since Release v1.1.0 * @return string The Base58 encoded string. */ - public function encode($string) + public function encode(string $string) : string { - // Type validation - if (is_string($string) === false) { - throw new InvalidArgumentException('Argument $string must be a string.'); - } - // If the string is empty, then the encoded string is obviously empty if (strlen($string) === 0) { return ''; @@ -105,13 +95,8 @@ public function encode($string) * @since Release v1.1.0 * @return string Returns the decoded string. */ - public function decode($base58) + public function decode(string $base58) : string { - // Type Validation - if (is_string($base58) === false) { - throw new InvalidArgumentException('Argument $base58 must be a string.'); - } - // If the string is empty, then the decoded string is obviously empty if (strlen($base58) === 0) { return ''; diff --git a/src/ServiceInterface.php b/src/ServiceInterface.php index 0fe3745..71ccf84 100644 --- a/src/ServiceInterface.php +++ b/src/ServiceInterface.php @@ -11,7 +11,7 @@ interface ServiceInterface * @since v1.1.0 * @return string The Base58 encoded string. */ - public function encode($string); + public function encode(string $string) : string; /** * Decode base58 into a PHP string. @@ -20,5 +20,5 @@ public function encode($string); * @since v1.1.0 * @return string Returns the decoded string. */ - public function decode($base58); + public function decode(string $base58) : string; } diff --git a/tests/Base58Test.php b/tests/Base58Test.php index bf135be..7280ec3 100644 --- a/tests/Base58Test.php +++ b/tests/Base58Test.php @@ -3,58 +3,49 @@ use StephenHill\Base58; use StephenHill\BCMathService; use StephenHill\GMPService; +use PHPUnit\Framework\TestCase; +use PHPUnit\Framework\Attributes\DataProvider; -class Base58Tests extends PHPUnit_Framework_TestCase +class Base58Test extends TestCase { - /** - * @dataProvider encodingsProvider - */ - public function testEncode($string, $encoded, $instance) + #[DataProvider('encodingsProvider')] + public function testEncode(string $string, string $encoded, Base58 $instance): void { - $string = (string) $string; - $encoded = (string) $encoded; - $this->assertSame($encoded, $instance->encode($string)); } - /** - * @dataProvider encodingsProvider - */ - public function testDecode($string, $encoded, $instance) + #[DataProvider('encodingsProvider')] + public function testDecode(string $string, string $encoded, Base58 $instance): void { - $string = (string) $string; - $encoded = (string) $encoded; - $this->assertSame($string, $instance->decode($encoded)); } - public function encodingsProvider() + public static function encodingsProvider(): array { - $instances = array( + $instances = [ new Base58(null, new BCMathService()), - new Base58(null, new GMPService()) - ); - - $tests = array( - array('', ''), - array('1', 'r'), - array('a', '2g'), - array('bbb', 'a3gV'), - array('ccc', 'aPEr'), - array('hello!', 'tzCkV5Di'), - array('Hello World', 'JxF12TrwUP45BMd'), - array('this is a test', 'jo91waLQA1NNeBmZKUF'), - array('the quick brown fox', 'NK2qR8Vz63NeeAJp9XRifbwahu'), - array('THE QUICK BROWN FOX', 'GRvKwF9B69ssT67JgRWxPQTZ2X'), - array('simply a long string', '2cFupjhnEsSn59qHXstmK2ffpLv2'), - array("\x00\x61", '12g'), - array("\x00", '1'), - array("\x00\x00", '11'), - array('0248ac9d3652ccd8350412b83cb08509e7e4bd41', '3PtvAWwSMPe2DohNuCFYy76JhMV3rhxiSxQMbPBTtiPvYvneWu95XaY') - ); + new Base58(null, new GMPService()), + ]; - $return = array(); + $tests = [ + ['', ''], + ['1', 'r'], + ['a', '2g'], + ['bbb', 'a3gV'], + ['ccc', 'aPEr'], + ['hello!', 'tzCkV5Di'], + ['Hello World', 'JxF12TrwUP45BMd'], + ['this is a test', 'jo91waLQA1NNeBmZKUF'], + ['the quick brown fox', 'NK2qR8Vz63NeeAJp9XRifbwahu'], + ['THE QUICK BROWN FOX', 'GRvKwF9B69ssT67JgRWxPQTZ2X'], + ['simply a long string', '2cFupjhnEsSn59qHXstmK2ffpLv2'], + ["\x00\x61", '12g'], + ["\x00", '1'], + ["\x00\x00", '11'], + ['0248ac9d3652ccd8350412b83cb08509e7e4bd41', '3PtvAWwSMPe2DohNuCFYy76JhMV3rhxiSxQMbPBTtiPvYvneWu95XaY'], + ]; + $return = []; foreach ($instances as $instance) { foreach ($tests as $test) { $test[] = $instance; @@ -65,50 +56,19 @@ public function encodingsProvider() return $return; } - /** - * @expectedException InvalidArgumentException - * @expectedExceptionMessage Argument $alphabet must be a string. - */ - public function testConstructorTypeException() + public function testConstructorLengthException(): void { - new Base58(intval(123)); - } + $this->expectException(\InvalidArgumentException::class); + $this->expectExceptionMessage('Argument $alphabet must contain 58 characters.'); - /** - * @expectedException InvalidArgumentException - * @expectedExceptionMessage Argument $alphabet must contain 58 characters. - */ - public function testConstructorLengthException() - { new Base58(''); } - /** - * @expectedException InvalidArgumentException - * @expectedExceptionMessage Argument $string must be a string. - */ - public function testEncodeTypeException() - { - $base58 = new Base58(); - $base58->encode(intval(123)); - } - - /** - * @expectedException InvalidArgumentException - * @expectedExceptionMessage Argument $base58 must be a string. - */ - public function testDecodeTypeException() + public function testInvalidBase58(): void { - $base58 = new Base58(); - $base58->decode(intval(123)); - } + $this->expectException(\InvalidArgumentException::class); + $this->expectExceptionMessage('Argument $base58 contains invalid characters.'); - /** - * @expectedException InvalidArgumentException - * @expectedExceptionMessage Argument $base58 contains invalid characters. - */ - public function testInvalidBase58() - { $base58 = new Base58(); $base58->decode("This isn't valid base58"); }