diff --git a/src/Utils/Abi/ArgumentDecoder.php b/src/Utils/Abi/ArgumentDecoder.php index eac3fbc1..3efc708e 100644 --- a/src/Utils/Abi/ArgumentDecoder.php +++ b/src/Utils/Abi/ArgumentDecoder.php @@ -12,7 +12,13 @@ final class ArgumentDecoder public function __construct(string $bytes) { - $bytes = hex2bin($bytes); + try { + $bytes = hex2bin($bytes); + } catch (\Throwable $e) { + // Handle the case where hex2bin fails, e.g., invalid hex string + $bytes = false; + } + if ($bytes === false) { $bytes = ''; } diff --git a/src/Utils/Message.php b/src/Utils/Message.php index 3e1ef91a..311f0dfb 100644 --- a/src/Utils/Message.php +++ b/src/Utils/Message.php @@ -44,16 +44,11 @@ class Message */ public function __construct(object $message) { - if (property_exists($message, 'publickey')) { - $this->publicKey = $message->publickey; - } elseif (property_exists($message, 'publicKey')) { - $this->publicKey = $message->publicKey; - } elseif (property_exists($message, 'signatory')) { - $this->publicKey = $message->signatory; - } else { + if (! property_exists($message, 'publicKey')) { throw new InvalidArgumentException('The given message did not contain a valid public key.'); } + $this->publicKey = $message->publicKey; $this->signature = $message->signature; $this->message = $message->message; } @@ -113,7 +108,7 @@ public static function sign(string $message, string $passphrase): self $v = dechex($signature->getRecoveryId() + 27); return static::new([ - 'publickey' => $privateKey->publicKey, + 'publicKey' => $privateKey->publicKey, 'signature' => $r.$s.$v, 'message' => $message, ]); @@ -144,7 +139,7 @@ public function verify(): bool public function toArray(): array { return [ - 'publickey' => $this->publicKey, + 'publicKey' => $this->publicKey, 'signature' => $this->signature, 'message' => $this->message, ]; diff --git a/tests/Unit/Utils/Abi/ArgumentDecoderTest.php b/tests/Unit/Utils/Abi/ArgumentDecoderTest.php index 0c388b50..df0d7cb7 100644 --- a/tests/Unit/Utils/Abi/ArgumentDecoderTest.php +++ b/tests/Unit/Utils/Abi/ArgumentDecoderTest.php @@ -19,6 +19,15 @@ expect($decoder->decodeAddress())->toBe($expected); }); +it('should decode a string', function () { + $payload = '0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000474657374'; + $expected = 'test'; + + $decoder = new ArgumentDecoder($payload); + + expect($decoder->decodeString())->toBe($expected); +}); + it('should decode unsigned int', function () { $payload = '000000000000000000000000000000000000000000000000016345785d8a0000'; $expected = '100000000000000000'; @@ -54,3 +63,12 @@ expect($decoder->decodeBool())->toBe($expected); }); + +it('should handle issue converting hex to binary', function () { + $decoder = new ArgumentDecoder('invalid'); + + $reflectionProperty = new \ReflectionProperty(ArgumentDecoder::class, 'bytes'); + $reflectionProperty->setAccessible(true); + + expect($reflectionProperty->getValue($decoder))->toBe(''); +}); diff --git a/tests/Unit/Utils/AddressTest.php b/tests/Unit/Utils/AddressTest.php index 6f0ba7bb..b70e8daa 100644 --- a/tests/Unit/Utils/AddressTest.php +++ b/tests/Unit/Utils/AddressTest.php @@ -2,6 +2,7 @@ declare(strict_types=1); +use ArkEcosystem\Crypto\ByteBuffer\ByteBuffer; use ArkEcosystem\Crypto\Utils\Address as TestClass; test('it should validate the address', function () { @@ -17,3 +18,19 @@ expect($actual)->toBeFalse(); }); + +it('should convert to hex string', function () { + $fixture = $this->getFixture('identity'); + + $actual = TestClass::toBufferHexString($fixture['data']['address']); + + expect($actual)->toBe(substr($fixture['data']['address'], 2)); +}); + +it('should extract address from a byte buffer', function () { + $fixture = $this->getFixture('identity'); + + $actual = TestClass::fromByteBuffer(ByteBuffer::fromHex(substr($fixture['data']['address'], 2))); + + expect($actual)->toBe($fixture['data']['address']); +}); diff --git a/tests/Unit/Utils/MessageTest.php b/tests/Unit/Utils/MessageTest.php index 2ce906b2..35093fee 100644 --- a/tests/Unit/Utils/MessageTest.php +++ b/tests/Unit/Utils/MessageTest.php @@ -34,6 +34,14 @@ expect($message->message)->toBe($fixture['message']); }); +test('it should throw if no public key is provided', function () { + $fixture = $this->getFixture('message-sign'); + + unset($fixture['publicKey']); + + Message::new($fixture); +})->throws(InvalidArgumentException::class, 'The given message did not contain a valid public key.'); + test('it should create a message from a string', function () { $fixture = $this->getFixture('message-sign'); diff --git a/tests/Unit/Utils/TransactionUtilsTest.php b/tests/Unit/Utils/TransactionUtilsTest.php new file mode 100644 index 00000000..c45005a7 --- /dev/null +++ b/tests/Unit/Utils/TransactionUtilsTest.php @@ -0,0 +1,80 @@ +getTransactionFixture('evm_call', 'username-resignation'); + + $transaction = TransactionUtils::toBuffer($fixture['data']); + + expect($transaction->getHex())->toBe($fixture['serialized']); +}); + +it('should convert a transaction to a buffer when data starts with 0x', function () { + $fixture = $this->getTransactionFixture('evm_call', 'username-resignation'); + + $fixture['data']['data'] = '0x'.$fixture['data']['data']; + + $transaction = TransactionUtils::toBuffer($fixture['data']); + + expect($transaction->getHex())->toBe($fixture['serialized']); +}); + +it('should get the hash for a transaction', function () { + $fixture = $this->getTransactionFixture('evm_call', 'username-resignation'); + + $transaction = TransactionUtils::toHash($fixture['data']); + + expect($transaction->getHex())->toBe($fixture['data']['hash']); +}); + +it('should handle string data starting with 0x', function () { + $fixture = $this->getTransactionFixture('evm_call', 'username-resignation'); + + $fixture['data']['gasPrice'] = '0x'.dechex($fixture['data']['gasPrice']); + + $transaction = TransactionUtils::toBuffer($fixture['data']); + + expect($transaction->getHex())->toBe($fixture['serialized']); +}); + +it('should handle BigDecimal value', function () { + $fixture = $this->getTransactionFixture('evm_call', 'username-resignation'); + + $fixture['data']['gasPrice'] = BigDecimal::of($fixture['data']['gasPrice']); + + $transaction = TransactionUtils::toBuffer($fixture['data']); + + expect($transaction->getHex())->toBe($fixture['serialized']); +}); + +it('should handle zero BigDecimal value', function () { + $fixture = $this->getTransactionFixture('evm_call', 'username-resignation'); + + $fixture['data']['gasPrice'] = BigDecimal::zero(); + + $transaction = TransactionUtils::toBuffer($fixture['data'], true); + + $decoded = RlpDecoder::decode('0x'.substr($transaction->getHex(), 2)); + + expect($decoded[3])->toBe('0x'); +}); + +it('should handle unknown value value', function () { + $fixture = $this->getTransactionFixture('evm_call', 'username-resignation'); + + $fixture['data']['gasPrice'] = 123.456; + + $transaction = TransactionUtils::toBuffer($fixture['data'], true); + + $decoded = RlpDecoder::decode('0x'.substr($transaction->getHex(), 2)); + + expect($decoded[3])->toBe('0x'); +}); + +// toBuffer +// toHash