@@ -19,7 +19,7 @@ import { EthereumJSErrorWithoutCode } from './errors.ts'
19
19
import { assertIsBytes , assertIsHexString , assertIsString } from './helpers.ts'
20
20
import { stripHexPrefix } from './internal.ts'
21
21
22
- import type { BigIntLike , BytesLike , PrefixedHexString } from './types.ts'
22
+ import type { BigIntLike , BytesLike , NestedUint8Array , PrefixedHexString } from './types.ts'
23
23
24
24
export interface AccountData {
25
25
nonce ?: BigIntLike
@@ -39,6 +39,35 @@ export interface PartialAccountData {
39
39
40
40
export type AccountBodyBytes = [ Uint8Array , Uint8Array , Uint8Array , Uint8Array ]
41
41
42
+ /**
43
+ * Handles the null indicator for RLP encoded accounts
44
+ * @returns {null } is the null indicator is 0
45
+ * @returns The unchanged value is the null indicator is 1
46
+ * @throws if the null indicator is > 1
47
+ * @throws if the length of values is < 2
48
+ * @param value The value to convert
49
+ * @returns The converted value
50
+ */
51
+ function handleNullIndicator ( values : NestedUint8Array | Uint8Array ) : Uint8Array | null {
52
+ // Needed if some values are not provided to the array (e.g. partial account RLP)
53
+ if ( values [ 0 ] === undefined ) {
54
+ return null
55
+ }
56
+
57
+ const nullIndicator = bytesToInt ( values [ 0 ] as Uint8Array )
58
+
59
+ if ( nullIndicator === 0 ) {
60
+ return null
61
+ }
62
+ if ( nullIndicator > 1 ) {
63
+ throw EthereumJSErrorWithoutCode ( `Invalid isNullIndicator=${ nullIndicator } ` )
64
+ }
65
+ if ( values . length < 2 ) {
66
+ throw EthereumJSErrorWithoutCode ( `Invalid values length=${ values . length } ` )
67
+ }
68
+ return values [ 1 ] as Uint8Array
69
+ }
70
+
42
71
/**
43
72
* Account class to load and maintain the basic account objects.
44
73
* Supports partial loading and access required for verkle with null
@@ -126,8 +155,10 @@ export class Account {
126
155
127
156
/**
128
157
* This constructor assigns and validates the values.
129
- * Use the static factory methods to assist in creating an Account from varying data types.
130
- * undefined get assigned with the defaults present, but null args are retained as is
158
+ * It is not recommended to use this constructor directly. Instead use the static
159
+ * factory methods to assist in creating an Account from varying data types.
160
+ * undefined get assigned with the defaults, but null args are retained as is
161
+ * @deprecated
131
162
*/
132
163
constructor (
133
164
nonce : bigint | null = BIGINT_0 ,
@@ -325,91 +356,26 @@ export function createAccountFromRLP(serialized: Uint8Array) {
325
356
}
326
357
327
358
export function createPartialAccountFromRLP ( serialized : Uint8Array ) {
328
- const values = RLP . decode ( serialized ) as Uint8Array [ ] [ ]
359
+ const values = RLP . decode ( serialized )
329
360
330
361
if ( ! Array . isArray ( values ) ) {
331
362
throw EthereumJSErrorWithoutCode ( 'Invalid serialized account input. Must be array' )
332
363
}
333
364
334
- let nonce = null
335
- if ( ! Array . isArray ( values [ 0 ] ) ) {
336
- throw EthereumJSErrorWithoutCode ( 'Invalid partial nonce encoding. Must be array' )
337
- } else {
338
- const isNotNullIndicator = bytesToInt ( values [ 0 ] [ 0 ] )
339
- if ( isNotNullIndicator !== 0 && isNotNullIndicator !== 1 ) {
340
- throw EthereumJSErrorWithoutCode ( `Invalid isNullIndicator=${ isNotNullIndicator } for nonce` )
341
- }
342
- if ( isNotNullIndicator === 1 ) {
343
- nonce = bytesToBigInt ( values [ 0 ] [ 1 ] )
365
+ for ( const value of values ) {
366
+ // Ensure that each array item is an array
367
+ if ( ! Array . isArray ( value ) ) {
368
+ throw EthereumJSErrorWithoutCode ( 'Invalid partial encoding. Each item must be an array' )
344
369
}
345
370
}
346
371
347
- let balance = null
348
- if ( ! Array . isArray ( values [ 1 ] ) ) {
349
- throw EthereumJSErrorWithoutCode ( 'Invalid partial balance encoding. Must be array' )
350
- } else {
351
- const isNotNullIndicator = bytesToInt ( values [ 1 ] [ 0 ] )
352
- if ( isNotNullIndicator !== 0 && isNotNullIndicator !== 1 ) {
353
- throw EthereumJSErrorWithoutCode ( `Invalid isNullIndicator=${ isNotNullIndicator } for balance` )
354
- }
355
- if ( isNotNullIndicator === 1 ) {
356
- balance = bytesToBigInt ( values [ 1 ] [ 1 ] )
357
- }
358
- }
372
+ const [ nonceRaw , balanceRaw , storageRoot , codeHash , codeSizeRaw , versionRaw ] =
373
+ values . map ( handleNullIndicator )
359
374
360
- let storageRoot = null
361
- if ( ! Array . isArray ( values [ 2 ] ) ) {
362
- throw EthereumJSErrorWithoutCode ( 'Invalid partial storageRoot encoding. Must be array' )
363
- } else {
364
- const isNotNullIndicator = bytesToInt ( values [ 2 ] [ 0 ] )
365
- if ( isNotNullIndicator !== 0 && isNotNullIndicator !== 1 ) {
366
- throw EthereumJSErrorWithoutCode (
367
- `Invalid isNullIndicator=${ isNotNullIndicator } for storageRoot` ,
368
- )
369
- }
370
- if ( isNotNullIndicator === 1 ) {
371
- storageRoot = values [ 2 ] [ 1 ]
372
- }
373
- }
374
-
375
- let codeHash = null
376
- if ( ! Array . isArray ( values [ 3 ] ) ) {
377
- throw EthereumJSErrorWithoutCode ( 'Invalid partial codeHash encoding. Must be array' )
378
- } else {
379
- const isNotNullIndicator = bytesToInt ( values [ 3 ] [ 0 ] )
380
- if ( isNotNullIndicator !== 0 && isNotNullIndicator !== 1 ) {
381
- throw EthereumJSErrorWithoutCode ( `Invalid isNullIndicator=${ isNotNullIndicator } for codeHash` )
382
- }
383
- if ( isNotNullIndicator === 1 ) {
384
- codeHash = values [ 3 ] [ 1 ]
385
- }
386
- }
387
-
388
- let codeSize = null
389
- if ( ! Array . isArray ( values [ 4 ] ) ) {
390
- throw EthereumJSErrorWithoutCode ( 'Invalid partial codeSize encoding. Must be array' )
391
- } else {
392
- const isNotNullIndicator = bytesToInt ( values [ 4 ] [ 0 ] )
393
- if ( isNotNullIndicator !== 0 && isNotNullIndicator !== 1 ) {
394
- throw EthereumJSErrorWithoutCode ( `Invalid isNullIndicator=${ isNotNullIndicator } for codeSize` )
395
- }
396
- if ( isNotNullIndicator === 1 ) {
397
- codeSize = bytesToInt ( values [ 4 ] [ 1 ] )
398
- }
399
- }
400
-
401
- let version = null
402
- if ( ! Array . isArray ( values [ 5 ] ) ) {
403
- throw EthereumJSErrorWithoutCode ( 'Invalid partial version encoding. Must be array' )
404
- } else {
405
- const isNotNullIndicator = bytesToInt ( values [ 5 ] [ 0 ] )
406
- if ( isNotNullIndicator !== 0 && isNotNullIndicator !== 1 ) {
407
- throw EthereumJSErrorWithoutCode ( `Invalid isNullIndicator=${ isNotNullIndicator } for version` )
408
- }
409
- if ( isNotNullIndicator === 1 ) {
410
- version = bytesToInt ( values [ 5 ] [ 1 ] )
411
- }
412
- }
375
+ const nonce = nonceRaw === null ? null : bytesToBigInt ( nonceRaw )
376
+ const balance = balanceRaw === null ? null : bytesToBigInt ( balanceRaw )
377
+ const codeSize = codeSizeRaw === null ? null : bytesToInt ( codeSizeRaw )
378
+ const version = versionRaw === null ? null : bytesToInt ( versionRaw )
413
379
414
380
return createPartialAccount ( { balance, nonce, storageRoot, codeHash, codeSize, version } )
415
381
}
0 commit comments