Skip to content

Commit

Permalink
fix account copy issue (hyperledger#6845)
Browse files Browse the repository at this point in the history
Signed-off-by: Karim Taam <[email protected]>
  • Loading branch information
matkt authored Mar 29, 2024
1 parent d8e1e17 commit eab55f7
Show file tree
Hide file tree
Showing 3 changed files with 121 additions and 21 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ public BonsaiAccount(
toCopy.nonce,
toCopy.balance,
toCopy.codeHash,
toCopy.code,
mutable);
this.storageRoot = toCopy.storageRoot;
updatedStorage.putAll(toCopy.updatedStorage);
Expand All @@ -96,6 +97,7 @@ public BonsaiAccount(
tracked.getNonce(),
tracked.getBalance(),
tracked.getCodeHash(),
tracked.getCode(),
true);
this.storageRoot = Hash.EMPTY_TRIE_HASH;
updatedStorage.putAll(tracked.getUpdatedStorage());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,22 @@ public abstract class DiffBasedAccount implements MutableAccount, AccountValue {

protected final Map<UInt256, UInt256> updatedStorage = new HashMap<>();

/**
* Constructs a new DiffBasedAccount instance without the account's code. This constructor is used
* when the account's code is not required or will not be read from the database. It initializes
* the account with its context, address, address hash, nonce, balance, code hash, and mutability
* status.
*
* @param context The DiffBasedWorldView context in which this account exists.
* @param address The Ethereum address of this account.
* @param addressHash The hash of the account's address.
* @param nonce The nonce of the account, representing the number of transactions sent from this
* account.
* @param balance The balance of the account in Wei.
* @param codeHash The hash of the account's code.
* @param mutable A boolean indicating if the account is mutable. If false, the account is
* considered immutable.
*/
public DiffBasedAccount(
final DiffBasedWorldView context,
final Address address,
Expand All @@ -60,32 +76,40 @@ public DiffBasedAccount(
this.immutable = !mutable;
}

/**
* Constructs a new DiffBasedAccount instance with the account's code. This constructor is used
* when all account information, including its code, are available. It initializes the account
* with its context, address, address hash, nonce, balance, code hash, the actual code, and
* mutability status.
*
* @param context The DiffBasedWorldView context in which this account exists.
* @param address The Ethereum address of this account.
* @param addressHash The hash of the account's address.
* @param nonce The nonce of the account, representing the number of transactions sent from this
* account.
* @param balance The balance of the account in Wei.
* @param codeHash The hash of the account's code.
* @param code The actual bytecode of the account's smart contract. This is provided when the code
* is known and needs to be associated with the account.
* @param mutable A boolean indicating if the account is mutable. If false, the account is
* considered immutable.
*/
public DiffBasedAccount(
final DiffBasedWorldView context,
final Address address,
final AccountValue stateTrieAccount,
final Hash addressHash,
final long nonce,
final Wei balance,
final Hash codeHash,
final Bytes code,
final boolean mutable) {
this(
context,
address,
address.addressHash(),
stateTrieAccount.getNonce(),
stateTrieAccount.getBalance(),
stateTrieAccount.getCodeHash(),
mutable);
}

public DiffBasedAccount(
final DiffBasedAccount toCopy, final DiffBasedWorldView context, final boolean mutable) {
this.context = context;
this.address = toCopy.address;
this.addressHash = toCopy.addressHash;
this.nonce = toCopy.nonce;
this.balance = toCopy.balance;
this.codeHash = toCopy.codeHash;
this.code = toCopy.code;
updatedStorage.putAll(toCopy.updatedStorage);

this.address = address;
this.addressHash = addressHash;
this.nonce = nonce;
this.balance = balance;
this.codeHash = codeHash;
this.code = code;
this.immutable = !mutable;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
/*
* Copyright Hyperledger Besu Contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.besu.ethereum.trie.diffbased.bonsai;

import static org.assertj.core.api.Assertions.assertThat;

import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.datatypes.Hash;
import org.hyperledger.besu.datatypes.Wei;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.worldview.BonsaiWorldState;
import org.hyperledger.besu.evm.worldstate.UpdateTrackingAccount;

import org.apache.tuweni.bytes.Bytes;
import org.apache.tuweni.units.bigints.UInt256;
import org.junit.jupiter.api.Test;
import org.mockito.Mock;

public class BonsaiAccountTest {

@Mock BonsaiWorldState bonsaiWorldState;

@Test
void shouldCopyTrackedBonsaiAccountCorrectly() {
final BonsaiAccount trackedAccount =
new BonsaiAccount(
bonsaiWorldState,
Address.ZERO,
Hash.hash(Address.ZERO),
0,
Wei.ONE,
Hash.EMPTY_TRIE_HASH,
Hash.EMPTY,
true);
trackedAccount.setCode(Bytes.of(1));
final UpdateTrackingAccount<BonsaiAccount> bonsaiAccountUpdateTrackingAccount =
new UpdateTrackingAccount<>(trackedAccount);
bonsaiAccountUpdateTrackingAccount.setStorageValue(UInt256.ONE, UInt256.ONE);

final BonsaiAccount expectedAccount = new BonsaiAccount(trackedAccount, bonsaiWorldState, true);
expectedAccount.setStorageValue(UInt256.ONE, UInt256.ONE);
assertThat(new BonsaiAccount(bonsaiWorldState, bonsaiAccountUpdateTrackingAccount))
.isEqualToComparingFieldByField(expectedAccount);
}

@Test
void shouldCopyBonsaiAccountCorrectly() {
final BonsaiAccount account =
new BonsaiAccount(
bonsaiWorldState,
Address.ZERO,
Hash.hash(Address.ZERO),
0,
Wei.ONE,
Hash.EMPTY_TRIE_HASH,
Hash.EMPTY,
true);
account.setCode(Bytes.of(1));
account.setStorageValue(UInt256.ONE, UInt256.ONE);
assertThat(new BonsaiAccount(account, bonsaiWorldState, true))
.isEqualToComparingFieldByField(account);
}
}

0 comments on commit eab55f7

Please sign in to comment.