Ethereum Transaction Process Explained

·

Understanding how Ethereum transactions work under the hood is essential for developers, blockchain enthusiasts, and anyone interacting with the Ethereum network. This article dives deep into the technical flow of sending ETH via the Geth JavaScript console, unpacking the layers from user input to blockchain execution—without relying on third-party tools or wallets.

We’ll explore the inner workings of Geth’s JS runtime environment (JSRE), the role of RPC communication, and how Go-Ethereum processes transaction requests using reflection and modular service registration. By the end, you’ll have a clear picture of what happens when you call eth.sendTransaction().


How Ethereum Transactions Are Executed in the Geth Console

If you've used the Geth JavaScript console to send ETH, you might have run a command like:

eth.sendTransaction({from: "0x...", to: "0x...", value: web3.toWei(1, "ether")})

But what happens behind the scenes? Let’s break down the full execution pipeline—from your keystrokes in the console to the actual blockchain-level transaction processing.


The Core Flow: From JS Input to Blockchain Execution

When you type a command in the Geth console, it doesn’t directly interact with the blockchain. Instead, it goes through a well-defined sequence involving JavaScript interpretation, RPC bridging, and Go-based method dispatching.

Step 1: Console Initialization and JSRE Setup

When you run geth console, Geth initializes a JavaScript Runtime Environment (JSRE) powered by Otto—a Go-written JS interpreter. This allows JavaScript code to be executed within the Go process.

During initialization (console.New()), two critical components are injected into the JSRE:

👉 Discover how blockchain transactions really work under the hood.

This bridge is crucial—it enables JavaScript functions to trigger actual Ethereum operations by forwarding them over RPC to internal Go APIs.

Step 2: User Input and Command Evaluation

Once the console is active, it enters an interactive loop using Go channels (scheduler and abort) to handle input asynchronously. When you press Enter:

  1. Your input string (e.g., eth.sendTransaction(...)) is captured.
  2. The console.Evaluate() method passes it to jsre.Evaluate().
  3. Under the hood, Otto’s vm.Run() executes the script.

At this stage, any referenced web3 methods (like sendTransaction) are routed through the previously injected bridge.Send function.

Step 3: RPC Request Formation

Every JS API call—such as eth.accounts, personal.unlockAccount, or eth.sendTransaction—is translated into an RPC request inside bridge.Send. Here's what happens:

For example:

{
  "method": "eth_sendTransaction",
  "params": [{
    "from": "0x...",
    "to": "0x...",
    "value": "0xDE0B6B3A7640000"
  }],
  "id": 1
}

This request is then sent via b.client.Call(), which packages it into a message and transmits it internally—typically over IPC (Inter-Process Communication) when using geth attach.


Inside the RPC Server: Method Dispatching via Reflection

You won’t find a direct function named eth_sendTransaction in Go-Ethereum’s codebase. That’s because Ethereum uses reflection to dynamically map incoming RPC calls to actual Go methods.

Here’s how it works:

Request Parsing in rpc/json.go

The server receives raw JSON messages and parses them using parseRequest(). It splits the method name at the underscore:

elems := strings.Split("eth_sendTransaction", "_")
// elems[0] = "eth" → service namespace
// elems[1] = "sendTransaction" → method name

It then creates a rpcRequest object containing:

Service Registration and API Binding

Ethereum uses a modular architecture where each protocol (like eth, personal, net) registers itself as a service during node startup. Each service implements:

type Service interface {
    Protocols() []p2p.Protocol
    APIs() []rpc.API
}

The APIs() method returns available RPC endpoints. For example, the Ethereum protocol (eth) exposes:

API{
    Namespace: "eth",
    Service:   &PublicTransactionPoolAPI{},
    Public:    true,
}

During StartIPCEndpoint, these APIs are registered using handler.RegisterName("eth", service). Internally, Go reflection scans the service struct for exported methods and maps "sendTransaction" to the actual function.

👉 See how real-time blockchain interactions are powered by low-level APIs.


Final Step: Transaction Processing in Go-Ethereum

Now that we’ve traced the call from JS to Go, let’s identify the final destination of our transaction.

Despite seeing multiple SendTransaction methods in the codebase, only one matches our path:

func (s *PublicTransactionPoolAPI) SendTransaction(args interface{}) (common.Hash, error)

Why this one?

Before submission, EIP-155 replay protection is applied if the chain supports it (Spurious Dragon fork onward). This ensures transactions include chain ID in signature calculation, preventing cross-chain replay attacks.


Frequently Asked Questions

Q1: What is JSRE in Geth?

JSRE (JavaScript Runtime Environment) is a sandboxed environment in Geth built using Otto, a Go-based JavaScript interpreter. It allows users to interact with Ethereum via familiar web3.js syntax directly in the console.

Q2: How does Geth translate JS calls to Go functions?

Through a bridge mechanism (bridge.Send) that converts JavaScript method invocations into JSON-RPC calls. These are processed by a server that uses Go reflection to locate and invoke corresponding methods based on namespace and name.

Q3: Why can’t I find eth_sendTransaction in the source code?

Because it’s not explicitly defined. The method name is parsed at runtime, and the system uses reflection to map "eth" + "sendTransaction" to the actual Go method inside PublicTransactionPoolAPI.

Q4: What’s the difference between IPC and HTTP RPC in Geth?

IPC (Inter-Process Communication) is faster and restricted to local machine access via a Unix socket. HTTP RPC listens on a TCP port and allows remote connections but requires proper security configuration.

Q5: Is sending transactions via console secure?

It can be—if done locally with proper node security. Avoid exposing your RPC endpoint publicly or unlocking accounts for long periods. Use hardware wallets or signers for production environments.

Q6: What role does reflection play in Ethereum’s RPC system?

Reflection enables dynamic registration and invocation of API methods across different modules (eth, personal, etc.). It allows clean separation of concerns while maintaining a unified RPC interface.


Core Keywords


👉 Learn how developers build secure, scalable dApps using deep protocol insights.

Understanding the journey of an Ethereum transaction—from simple console input to reflection-driven Go execution—reveals the elegance of Ethereum’s design. Whether you're debugging, building tools, or just curious, knowing this flow empowers deeper engagement with one of the most influential blockchain platforms today.