TronRawSerializer.php 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. <?php
  2. namespace App\Helpers;
  3. use App\Helpers\TronHelper;
  4. class TronRawSerializer
  5. {
  6. public static function serializeRawData(array $rawData): string
  7. {
  8. $bin = '';
  9. // timestamp (field number = 1, wire type = 0)
  10. $bin .= self::encodeKey(1, 0);
  11. $bin .= self::encodeVarint($rawData['timestamp']);
  12. // ref_block_bytes (2, wire type = 2)
  13. $bin .= self::encodeKey(2, 2);
  14. $refBlockBytes = hex2bin($rawData['ref_block_bytes']);
  15. $bin .= self::encodeLengthDelimited($refBlockBytes);
  16. // ref_block_hash (3, wire type = 2)
  17. $bin .= self::encodeKey(3, 2);
  18. $refBlockHash = hex2bin($rawData['ref_block_hash']);
  19. $bin .= self::encodeLengthDelimited($refBlockHash);
  20. // expiration (4, wire type = 0)
  21. $bin .= self::encodeKey(4, 0);
  22. $bin .= self::encodeVarint($rawData['expiration']);
  23. // contract (5, repeated embedded message)
  24. foreach ($rawData['contract'] as $contract) {
  25. $bin .= self::encodeKey(5, 2);
  26. $contractBin = self::serializeContract($contract);
  27. $bin .= self::encodeLengthDelimited($contractBin);
  28. }
  29. // fee_limit (18, wire type = 0) — optional
  30. if (isset($rawData['fee_limit'])) {
  31. $bin .= self::encodeKey(18, 0);
  32. $bin .= self::encodeVarint($rawData['fee_limit']);
  33. }
  34. return $bin;
  35. }
  36. protected static function serializeContract(array $contract): string
  37. {
  38. $bin = '';
  39. // type (1, wire type = 0)
  40. $bin .= self::encodeKey(1, 0);
  41. $bin .= self::encodeVarint($contract['type']);
  42. // parameter (2, embedded)
  43. $bin .= self::encodeKey(2, 2);
  44. $parameterBin = self::serializeParameter($contract['parameter']);
  45. $bin .= self::encodeLengthDelimited($parameterBin);
  46. return $bin;
  47. }
  48. protected static function serializeParameter(array $param): string
  49. {
  50. $bin = '';
  51. if (isset($param['type_url'])) {
  52. // type_url (1)
  53. $bin .= self::encodeKey(1, 2);
  54. $bin .= self::encodeLengthDelimited($param['type_url']);
  55. }
  56. if (isset($param['value'])) {
  57. // value (2)
  58. $bin .= self::encodeKey(2, 2);
  59. $valueBin = self::serializeTriggerSmartContract($param['value']);
  60. $bin .= self::encodeLengthDelimited($valueBin);
  61. }
  62. return $bin;
  63. }
  64. protected static function serializeTriggerSmartContract(array $value): string
  65. {
  66. $bin = '';
  67. // owner_address (1)
  68. $bin .= self::encodeKey(1, 2);
  69. $bin .= self::encodeLengthDelimited(hex2bin($value['owner_address']));
  70. // contract_address (2)
  71. $bin .= self::encodeKey(2, 2);
  72. $bin .= self::encodeLengthDelimited(hex2bin($value['contract_address']));
  73. // call_value (3) — not used in TRC20
  74. // data (4)
  75. if (isset($value['data'])) {
  76. $bin .= self::encodeKey(4, 2);
  77. $bin .= self::encodeLengthDelimited(hex2bin($value['data']));
  78. }
  79. return $bin;
  80. }
  81. protected static function encodeKey($fieldNumber, $wireType): string
  82. {
  83. return self::encodeVarint(($fieldNumber << 3) | $wireType);
  84. }
  85. protected static function encodeVarint($value): string
  86. {
  87. $value = is_numeric($value) ? (int)$value : 0;
  88. $bin = '';
  89. while (true) {
  90. if (($value & ~0x7F) === 0) {
  91. $bin .= chr($value);
  92. break;
  93. } else {
  94. $bin .= chr(($value & 0x7F) | 0x80);
  95. $value >>= 7;
  96. }
  97. }
  98. return $bin;
  99. }
  100. protected static function encodeLengthDelimited(string $data): string
  101. {
  102. return self::encodeVarint(strlen($data)) . $data;
  103. }
  104. }