Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Gas consumption of different part of the deposit function call #1150

Closed
NIC619 opened this issue Feb 27, 2019 · 6 comments
Closed

Gas consumption of different part of the deposit function call #1150

NIC619 opened this issue Feb 27, 2019 · 6 comments

Comments

@NIC619
Copy link
Contributor

NIC619 commented Feb 27, 2019

Below are cumulative gas consumption of each part of deposit function call, starting from the beginning of the function:

def deposit(pubkey: bytes[PUBKEY_LENGTH],
            withdrawal_credentials: bytes[WITHDRAWAL_CREDENTIALS_LENGTH],
            signature: bytes[SIGNATURE_LENGTH]):
    # Avoid overflowing the Merkle tree (and prevent edge case in computing `self.branch`)
    assert self.deposit_count < MAX_DEPOSIT_COUNT

    # Validate deposit data
    deposit_amount: uint256 = msg.value / as_wei_value(1, "gwei")
    assert deposit_amount >= MIN_DEPOSIT_AMOUNT
    assert len(pubkey) == PUBKEY_LENGTH
    assert len(withdrawal_credentials) == WITHDRAWAL_CREDENTIALS_LENGTH
    assert len(signature) == SIGNATURE_LENGTH

    # cumulative gas consumption so far: ≈35304
    # NOTE: including basic transaction cost: 21000 + 68*176(assuming all non zero bytes inputs) = 32968
    # Emit `Deposit` log
    amount: bytes[8] = self.to_little_endian_64(deposit_amount)

    # cumulative gas consumption so far: ≈42583
    # NOTE: one `to_little_endian_64()` call consumes ≈6500 gas
   log.Deposit(pubkey, withdrawal_credentials, amount, signature, self.to_little_endian_64(self.deposit_count))

    # cumulative gas consumption so far: ≈67161
    # NOTE: one `to_little_endian_64()` call consumes ≈6500 gas
    # Compute `DepositData` root
    zero_bytes32: bytes32 = 0x0000000000000000000000000000000000000000000000000000000000000000
    pubkey_root: bytes32 = sha256(concat(pubkey, slice(zero_bytes32, start=0, len=64 - PUBKEY_LENGTH)))

    # cumulative gas consumption so far: ≈70434

    signature_root: bytes32 = sha256(concat(
        sha256(slice(signature, start=0, len=64)),
        sha256(concat(slice(signature, start=64, len=SIGNATURE_LENGTH - 64), zero_bytes32)),
    ))

    # cumulative gas consumption so far: ≈75661

    node: bytes32 = sha256(concat(
        sha256(concat(pubkey_root, withdrawal_credentials)),
        sha256(concat(amount, slice(zero_bytes32, start=0, len=32 - AMOUNT_LENGTH), signature_root)),
    ))

    # cumulative gas consumption so far: ≈81622
   # Add `DepositData` root to Merkle tree (update a single `branch` node)
    self.deposit_count += 1

    # cumulative gas consumption so far: ≈87271
    # NOTE: `self.deposit_count += 1` consumes 5000 gas (except for the first deposit which consumes 20000 gas)
    size: uint256 = self.deposit_count

    # cumulative gas consumption so far: ≈87486
   for height in range(DEPOSIT_CONTRACT_TREE_DEPTH):
        if bitwise_and(size, 1) == 1:  # More gas efficient than `size % 2 == 1`
            self.branch[height] = node
            # NOTE: `self.branch[height] = node` consumes 5000 gas or 20000 gas
            # depends on if `self.branch[height]` has been updated before
            break
        node = sha256(concat(self.branch[height], node))
        # NOTE: `node = sha256(concat(self.branch[height], node))`` consumes ≈1200 gas
        size /= 2
        # NOTE: `size /= 2` consumes ≈40 gas

       # cumulative gas consumption so far: ≈92651 and up (extra 15000 gas if `self.branch[height]` hasn't been updated before
       # and extra ≈1200 gas for each iteration in the loop
@hwwhww hwwhww transferred this issue from ethereum/deposit_contract Jun 8, 2019
@JustinDrake
Copy link
Contributor

@NIC619: This kind of gas analysis is helpful :) Would you mind updating the analysis using the code in #1152?

@NIC619
Copy link
Contributor Author

NIC619 commented Jun 10, 2019

Will do!

@JustinDrake
Copy link
Contributor

I advertised gas golfing on Twitter https://twitter.com/drakefjustin/status/1139989022577758211

@NIC619
Copy link
Contributor Author

NIC619 commented Jun 17, 2019

updated!

@jacqueswww
Copy link

Curious to see what the gas improvements are with vyperlang/vyper#1499

@JustinDrake
Copy link
Contributor

Thanks @NIC619, very clear breakdown. Looks like there isn't much fat.

Only two gas improvements were suggested from the golfing bounties:

  1. https://twitter.com/nicksdjohnson/status/1140018871513993216
  2. https://twitter.com/jadler0/status/1140422368323678209

Both seem minor enough to not bother impeding formal verification.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants