> ## Documentation Index
> Fetch the complete documentation index at: https://voltaire.tevm.sh/llms.txt
> Use this file to discover all available pages before exploring further.

# Rlp.flatten

> Flatten nested RLP list into array of byte values

<Card title="Try it Live" icon="play" href="https://playground.tevm.sh?example=primitives/rlp.ts">
  Run RLP examples in the interactive playground
</Card>

<Tabs />

## Flattening Order

`flatten` uses depth-first traversal:

```typescript theme={null}
import { Rlp } from 'tevm'

const nested = {
  type: 'list',
  value: [
    { type: 'bytes', value: new Uint8Array([1]) },      // #1
    {
      type: 'list',
      value: [
        { type: 'bytes', value: new Uint8Array([2]) },  // #2
        { type: 'bytes', value: new Uint8Array([3]) }   // #3
      ]
    },
    { type: 'bytes', value: new Uint8Array([4]) }       // #4
  ]
}

const flat = Rlp.flatten(nested)
// => [
//   { type: 'bytes', value: [1] },  // #1
//   { type: 'bytes', value: [2] },  // #2
//   { type: 'bytes', value: [3] },  // #3
//   { type: 'bytes', value: [4] }   // #4
// ]
```

## Usage Patterns

### Extract Transaction Fields

Extract all byte values from transaction:

```typescript theme={null}
import { Rlp } from 'tevm'

const txBytes = new Uint8Array([...])
const decoded = Rlp.decode(txBytes)

// Flatten to get all fields
const fields = Rlp.flatten(decoded.data)

// Access individual fields
const [nonce, gasPrice, gas, to, value, data, v, r, s] = fields.map(f => f.value)

console.log('Nonce:', nonce)
console.log('To:', to)
console.log('Signature r:', r)
```

### Extract Proof Nodes

Extract all nodes from Merkle proof:

```typescript theme={null}
import { Rlp } from 'tevm'

const proofBytes = new Uint8Array([...])
const decoded = Rlp.decode(proofBytes)

// Flatten to get all nodes
const nodes = Rlp.flatten(decoded.data).map(n => n.value)

console.log(`Proof has ${nodes.length} nodes`)

// Verify each node
for (const node of nodes) {
  verifyNode(node)
}
```

### Extract Log Data

Extract all data from event logs:

```typescript theme={null}
import { Rlp } from 'tevm'

const logBytes = new Uint8Array([...])
const decoded = Rlp.decode(logBytes)

// Flatten to get all byte values
const allData = Rlp.flatten(decoded.data)

// First item is address
const address = allData[0].value

// Topics follow
const topics = allData.slice(1, -1).map(t => t.value)

// Last item is data
const data = allData[allData.length - 1].value

console.log('Address:', address)
console.log('Topics:', topics)
console.log('Data:', data)
```

### Count Byte Values

Count total byte values in nested structure:

```typescript theme={null}
import { Rlp } from 'tevm'

function countByteValues(rlpData: BrandedRlp): number {
  return Rlp.flatten(rlpData).length
}

const nested = {
  type: 'list',
  value: [
    { type: 'bytes', value: new Uint8Array([1]) },
    {
      type: 'list',
      value: [
        { type: 'bytes', value: new Uint8Array([2]) },
        { type: 'bytes', value: new Uint8Array([3]) }
      ]
    }
  ]
}

const count = countByteValues(nested)
console.log(`Contains ${count} byte values`)  // 3
```

### Extract All Hashes

Extract all hash values from trie:

```typescript theme={null}
import { Rlp } from 'tevm'

function extractHashes(trieNode: BrandedRlp): Uint8Array[] {
  return Rlp.flatten(trieNode)
    .map(item => item.value)
    .filter(bytes => bytes.length === 32)  // Filter 32-byte hashes
}

const trieBytes = new Uint8Array([...])
const decoded = Rlp.decode(trieBytes)

const hashes = extractHashes(decoded.data)
console.log(`Found ${hashes.length} hashes`)
```

### Search for Value

Search for specific byte value in nested structure:

```typescript theme={null}
import { Rlp } from 'tevm'

function findValue(
  rlpData: BrandedRlp,
  target: Uint8Array
): boolean {
  const flattened = Rlp.flatten(rlpData)

  for (const item of flattened) {
    if (item.value.length === target.length) {
      if (item.value.every((b, i) => b === target[i])) {
        return true
      }
    }
  }

  return false
}

const nested = {...}
const target = new Uint8Array([1, 2, 3])

if (findValue(nested, target)) {
  console.log('Found target value')
}
```

### Calculate Total Data Size

Calculate total bytes in nested structure:

```typescript theme={null}
import { Rlp } from 'tevm'

function calculateTotalBytes(rlpData: BrandedRlp): number {
  return Rlp.flatten(rlpData).reduce(
    (sum, item) => sum + item.value.length,
    0
  )
}

const nested = {...}
const totalBytes = calculateTotalBytes(nested)
console.log(`Total: ${totalBytes} bytes`)
```

## Return Type

`flatten` returns an array of `BytesData`:

```typescript theme={null}
type BytesData = {
  type: "bytes"
  value: Uint8Array
}

// Example
const flat: BytesData[] = Rlp.flatten(data)

// Access values
for (const item of flat) {
  console.log('Type:', item.type)      // Always "bytes"
  console.log('Value:', item.value)    // Uint8Array
}
```

## Algorithm

Conceptual implementation:

```typescript theme={null}
function flatten(data: BrandedRlp): BytesData[] {
  const result: BytesData[] = []

  function visit(d: BrandedRlp) {
    if (d.type === 'bytes') {
      result.push(d)
    } else {
      // Recursively visit list items
      for (const item of d.value) {
        visit(item)
      }
    }
  }

  visit(data)
  return result
}
```

### Depth-first Traversal

```
Input:
┌─────────────────────┐
│ List                │
│ ├─ Bytes [1]        │  <-- Visit #1
│ └─ List             │
│    ├─ Bytes [2]     │  <-- Visit #2
│    └─ Bytes [3]     │  <-- Visit #3
└─────────────────────┘

Output:
[
  { type: 'bytes', value: [1] },  // #1
  { type: 'bytes', value: [2] },  // #2
  { type: 'bytes', value: [3] }   // #3
]
```

## Performance

### Complexity

* **Time**: O(n) where n is total number of items
* **Space**: O(n) for result array + O(d) for recursion depth

### vs Manual Extraction

`flatten` is more convenient than manual extraction:

```typescript theme={null}
import { Rlp } from 'tevm'

const decoded = Rlp.decode(bytes)

// Using flatten (simple)
const values = Rlp.flatten(decoded.data).map(item => item.value)

// Manual extraction (verbose)
const values: Uint8Array[] = []
function extract(data: BrandedRlp) {
  if (data.type === 'bytes') {
    values.push(data.value)
  } else {
    for (const item of data.value) {
      extract(item)
    }
  }
}
extract(decoded.data)
```

### Caching

Cache flattened results for repeated access:

```typescript theme={null}
import { Rlp } from 'tevm'

class FlatCache {
  private cache = new Map<string, BytesData[]>()

  flatten(data: BrandedRlp): BytesData[] {
    const key = Rlp.encode(data).toString()

    let cached = this.cache.get(key)
    if (!cached) {
      cached = Rlp.flatten(data)
      this.cache.set(key, cached)
    }

    return cached
  }
}
```

## See Also

* [decode](/primitives/rlp/decode) - Decode RLP bytes
* [equals](/primitives/rlp/equals) - Compare RLP data
* [Types](/primitives/rlp/types) - RLP type system
* [Usage Patterns](/primitives/rlp/usage-patterns) - Real-world examples
