"Executing the program" means validating the transaction that calls a function. Every node that validates the transaction "applies" the transaction over the same state (See block validation algorithm below). So if the initial system state is S[0]
, the transactions in the block will be applied to that state and the final state S[n]
will be computed. Each node will do the same when validating a block, starting with the same S[0]
and ending with the same S[n]
. The amount of ether in an account (to pay for the gas) is part of the system state. So gas used for execution on multiple nodes does not add up.
Here is an extract from https://github.com/ethereum/wiki/wiki/White-Paper#code-execution, explaining the basic block validation
- Check if the previous block referenced exists and is valid.
- Check that the timestamp of the block is greater than that of the referenced previous block and less than 15 minutes into the future
- Check that the block number, difficulty, transaction root, uncle root and gas limit (various low-level Ethereum-specific concepts) are
valid.
- Check that the proof of work on the block is valid.
- Let S[0] be the state at the end of the previous block.
- Let TX be the block's transaction list, with n transactions. For all i in 0...n-1, set S[i+1] = APPLY(S[i],TX[i]). If any application
returns an error, or if the total gas consumed in the block up until
this point exceeds the GASLIMIT, return an error.
- Let S_FINAL be S[n], but adding the block reward paid to the miner.
- Check if the Merkle tree root of the state S_FINAL is equal to the final state root provided in the block header. If it is, the block is
valid; otherwise, it is not valid.