assertMatchesRegularExpression('/^[0-9a-f]{130}$/', $sig); } #[Test] public function rejects_0x_prefixed_txid(): void { $this->expectException(RuntimeException::class); $this->expectExceptionMessageMatches('/^Invalid txID \(len=/'); TronSigner::signTxId(self::PRIVATE_KEY, '0x'.str_repeat('ab', 32)); } #[Test] public function rejects_truncated_txid_that_old_ltrim_would_produce(): void { // Old ltrim(..., '0x') would turn "00ab..." into "ab..." (62 chars). $this->expectException(RuntimeException::class); $this->expectExceptionMessageMatches('/^Invalid txID \(len=/'); TronSigner::signTxId(self::PRIVATE_KEY, str_repeat('ab', 31)); } #[Test] public function stress_signs_many_leading_zero_txids(): void { for ($i = 0; $i < 200; $i++) { $prefixZeros = random_int(1, 8); $txId = str_repeat('0', $prefixZeros).bin2hex(random_bytes(32)); $txId = substr($txId, 0, 64); $this->assertSame(64, strlen($txId)); $this->assertSame('0', $txId[0]); $sig = TronSigner::signTxId(self::PRIVATE_KEY, $txId); $this->assertMatchesRegularExpression('/^[0-9a-f]{130}$/', $sig); } } /** * @return array */ public static function validTxIds(): array { return [ 'no leading zero' => [str_repeat('ab', 32)], 'one leading zero' => ['0'.str_repeat('a', 63)], 'two leading zeros' => ['00'.str_repeat('b', 62)], 'many leading zeros' => [str_pad('deadbeef', 64, '0', STR_PAD_LEFT)], 'uppercase accepted after lower' => [strtoupper(str_repeat('cd', 32))], ]; } }