Aegis: refuse a Tron transaction whose fields appear twice
The decoder read the first copy of a singular protobuf field; java-tron keeps the last. Any.value is opaque bytes, so a TransferContract carrying two recipients and two amounts hashes to the same txid either way: the overlay showed "1 TRX to X" while the chain would move 999 TRX to another address. It also defeated the plan-time and sign-time draft checks against a hostile node. A repeated singular field, or a known field with the wrong wire type, now refuses the transaction.
This commit is contained in:
parent
8b74f5cbf9
commit
1db2c4265b
1 changed files with 14 additions and 3 deletions
|
|
@ -81,9 +81,20 @@ module.exports = function makeTronDecode({ sha256, base58check }) {
|
||||||
}
|
}
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
const one = (fields, n) => fields.find((f) => f.field === n);
|
// A singular field that appears twice is legal protobuf: the parser keeps
|
||||||
const bytesOf = (fields, n) => { const f = one(fields, n); return f && f.wire === 2 ? f.value : null; };
|
// the LAST copy (and merges repeated sub-messages). java-tron does that, so
|
||||||
const numOf = (fields, n) => { const f = one(fields, n); return f && f.wire === 0 ? f.value : null; };
|
// reading the first copy would show the user one recipient and amount while
|
||||||
|
// the chain executes another — and Any.value is opaque bytes, so the signed
|
||||||
|
// hash is the same either way. Refuse instead of guessing, and refuse a
|
||||||
|
// known field sent with the wrong wire type for the same reason.
|
||||||
|
const one = (fields, n, wire) => {
|
||||||
|
const hits = fields.filter((f) => f.field === n);
|
||||||
|
if (hits.length > 1) throw new Error(`field ${n} appears ${hits.length} times; refusing an ambiguous transaction`);
|
||||||
|
if (hits[0] && hits[0].wire !== wire) throw new Error(`field ${n} has wire type ${hits[0].wire}, expected ${wire}`);
|
||||||
|
return hits[0];
|
||||||
|
};
|
||||||
|
const bytesOf = (fields, n) => { const f = one(fields, n, 2); return f ? f.value : null; };
|
||||||
|
const numOf = (fields, n) => { const f = one(fields, n, 0); return f ? f.value : null; };
|
||||||
|
|
||||||
// 21-byte Tron address (0x41 || h20) → "T…" base58check. Anything else is
|
// 21-byte Tron address (0x41 || h20) → "T…" base58check. Anything else is
|
||||||
// returned as hex so the overlay never hides a malformed field.
|
// returned as hex so the overlay never hides a malformed field.
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue