fix(chain): canonical RLP for BSC sweeps + official RPC default
- EthSigner: encode r/s as minimal big-endian bytes (even-length only) instead of zero-padding to 32 bytes. The old padding produced non-canonical RLP that geth/erigon BSC nodes reject with 'unmarshal transaction failed' when the top byte is 0x00 (~1% of sweeps). Fixes broken BNB/USDT-BEP20 auto-sweep. - coruna.bsc.rpc_url default: switch from third-party bsc.publicnode.com to official BNB Chain Foundation https://bsc-dataseed.bnbchain.org (free, no API key). Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -48,8 +48,20 @@ final class EthSigner
|
||||
$key = $ec->keyFromPrivate($privateKeyHex);
|
||||
$sig = $key->sign($hash, ['canonical' => true]);
|
||||
|
||||
$r = str_pad($sig->r->toString(16), 64, '0', STR_PAD_LEFT);
|
||||
$s = str_pad($sig->s->toString(16), 64, '0', STR_PAD_LEFT);
|
||||
// Encode r/s as canonical big-endian integers (minimal bytes, no leading
|
||||
// zero bytes). Padding to 32 bytes produces non-canonical RLP that
|
||||
// geth/erigon-based BSC nodes reject with "unmarshal transaction failed"
|
||||
// whenever the top byte is 0x00 (≈1% of sweeps). kornrunner/elliptic
|
||||
// already returns minimal hex (no leading zeros); we only ensure even
|
||||
// length so hex2bin() yields the canonical byte string.
|
||||
$r = $sig->r->toString(16);
|
||||
$s = $sig->s->toString(16);
|
||||
if (strlen($r) % 2 !== 0) {
|
||||
$r = '0'.$r;
|
||||
}
|
||||
if (strlen($s) % 2 !== 0) {
|
||||
$s = '0'.$s;
|
||||
}
|
||||
$recovery = (int) ($sig->recoveryParam ?? 0);
|
||||
$v = (string) ($recovery + 35 + $chainId * 2);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user