Skip to content
This repository has been archived by the owner on Dec 5, 2024. It is now read-only.

Commit

Permalink
Update DAO rescue soft-fork rules
Browse files Browse the repository at this point in the history
(cherry picked from commit cc4fb4a)
  • Loading branch information
Nashatyrev committed Jun 28, 2016
1 parent 79a1947 commit e63dd90
Show file tree
Hide file tree
Showing 5 changed files with 57 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -48,5 +48,6 @@ public interface BlockchainConfig {
* @param repositoryTrack The repository track changed by transaction
* @return null if all is fine or String validation error
*/
String validateTransactionChanges(BlockStore blockStore, Block curBlock, RepositoryTrack repositoryTrack);
String validateTransactionChanges(BlockStore blockStore, Block curBlock, Transaction tx,
RepositoryTrack repositoryTrack);
}
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,8 @@ public boolean acceptTransactionSignature(Transaction tx) {
}

@Override
public String validateTransactionChanges(BlockStore blockStore, Block curBlock, RepositoryTrack repositoryTrack) {
public String validateTransactionChanges(BlockStore blockStore, Block curBlock, Transaction tx,
RepositoryTrack repositoryTrack) {
return null;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import org.ethereum.core.AccountState;
import org.ethereum.core.Block;
import org.ethereum.core.BlockHeader;
import org.ethereum.core.Transaction;
import org.ethereum.db.BlockStore;
import org.ethereum.db.ByteArrayWrapper;
import org.ethereum.db.RepositoryTrack;
Expand All @@ -19,36 +20,43 @@
*/
public class HomesteadDAOConfig extends HomesteadConfig {

public static final long DAO_RESCUE_BLOCK = 1_760_000;
public static final long DAO_RESCUE_BLOCK = 1_800_000;
public static final long DAO_RESCUE_GAS_LIMIT_TRIGGER = 4_000_000;
public static final byte[] DAO_CODE_HASH = Hex.decode("6a5d24750f78441e56fec050dc52fe8e911976485b7472faac7464a176a67caa");
public static final byte[][] WHITELISTED_RECIPIENTS = new byte[][] {
Hex.decode("Da4a4626d3E16e094De3225A751aAb7128e96526"),
Hex.decode("2ba9D006C1D72E67A70b5526Fc6b4b0C0fd6D334")
};


private final long daoRescueBlock;
private final long daoRescueGasLimitTrigger;
private final byte[] daoCodeHash;
private final byte[][] whitelist;
private Boolean rescue = null;

public HomesteadDAOConfig() {
this(DAO_RESCUE_BLOCK, DAO_RESCUE_GAS_LIMIT_TRIGGER, DAO_CODE_HASH);
this(DAO_RESCUE_BLOCK, DAO_RESCUE_GAS_LIMIT_TRIGGER, DAO_CODE_HASH, WHITELISTED_RECIPIENTS);
}

public HomesteadDAOConfig(Constants constants) {
this(constants, DAO_RESCUE_BLOCK, DAO_RESCUE_GAS_LIMIT_TRIGGER, DAO_CODE_HASH);
this(constants, DAO_RESCUE_BLOCK, DAO_RESCUE_GAS_LIMIT_TRIGGER, DAO_CODE_HASH, WHITELISTED_RECIPIENTS);
}

public HomesteadDAOConfig(long daoRescueBlock, long daoRescueGasLimitTrigger, byte[] daoCodeHash) {
public HomesteadDAOConfig(long daoRescueBlock, long daoRescueGasLimitTrigger, byte[] daoCodeHash, byte[][] whitelist) {
this.daoRescueBlock = daoRescueBlock;
this.daoRescueGasLimitTrigger = daoRescueGasLimitTrigger;
this.daoCodeHash = daoCodeHash;
this.whitelist = whitelist;
}

public HomesteadDAOConfig(Constants constants, long daoRescueBlock, long daoRescueGasLimitTrigger,
byte[] daoCodeHash) {
byte[] daoCodeHash, byte[][] whitelist) {
super(constants);
this.daoRescueBlock = daoRescueBlock;
this.daoRescueGasLimitTrigger = daoRescueGasLimitTrigger;
this.daoCodeHash = daoCodeHash;
this.whitelist = whitelist;
}

private boolean shouldRescueDAO(BlockStore bs, Block curBlock) {
Expand All @@ -74,7 +82,8 @@ private boolean shouldRescueDAO(BlockStore bs, Block curBlock) {
}

@Override
public String validateTransactionChanges(BlockStore blockStore, Block curBlock, RepositoryTrack repositoryTrack) {
public String validateTransactionChanges(BlockStore blockStore, Block curBlock, Transaction tx,
RepositoryTrack repositoryTrack) {
if (shouldRescueDAO(blockStore, curBlock)) {
Set<ByteArrayWrapper> changedAddresses = repositoryTrack.getFullAddressSet();
for (ByteArrayWrapper address : changedAddresses) {
Expand All @@ -84,7 +93,13 @@ public String validateTransactionChanges(BlockStore blockStore, Block curBlock,
BigInteger newBalance = repositoryTrack.getBalance(address.getData());
BigInteger oldBalance = repositoryTrack.getOriginRepository().getBalance(address.getData());
if (newBalance.compareTo(oldBalance) < 0) {
return String.format("RescueDAO: DAO balance decrease %s > %s", oldBalance, newBalance);
for (byte[] whiteRecipient : whitelist) {
if (FastByteComparisons.equal(tx.getReceiveAddress(), whiteRecipient)) {
return null;
}
}
return String.format("RescueDAO: DAO balance decrease %s > %s, recipient is not whitelisted: %s",
oldBalance, newBalance, Hex.toHexString(tx.getReceiveAddress()));
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -295,7 +295,7 @@ public void finalization() {
if (!readyToExecute) return;

String err = SystemProperties.CONFIG.getBlockchainConfig().getConfigForBlock(currentBlock.getNumber()).
validateTransactionChanges(blockStore, currentBlock, (RepositoryTrack) cacheTrack);
validateTransactionChanges(blockStore, currentBlock, tx, (RepositoryTrack) cacheTrack);
if (err != null) {
execError(err);
m_endGas = toBI(tx.getGasLimit());
Expand Down
38 changes: 30 additions & 8 deletions ethereumj-core/src/test/java/org/ethereum/core/DAORescueTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,11 @@ public BigInteger getMINIMUM_DIFFICULTY() {
"function robDao(address daoAddr) {" +
" TestDAO(daoAddr).withdraw();" +
"}" +
"}" +
"contract WhiteHat {" +
"function saveDao(address daoAddr) {" +
" TestDAO(daoAddr).withdraw();" +
"}" +
"}";

@BeforeClass
Expand All @@ -50,11 +55,13 @@ public static void setup() throws Exception {
StandaloneBlockchain bc = new StandaloneBlockchain().withAutoblock(true);
SolidityContract dao = bc.submitNewContract(daoEmulator, "TestDAO");
final byte[] codeHash = bc.getBlockchain().getRepository().getAccountState(dao.getAddress()).getCodeHash();
SolidityContract white = bc.submitNewContract(daoEmulator, "WhiteHat");
final byte[] whiteAddr = white.getAddress();

SystemProperties.CONFIG.setBlockchainConfig(new AbstractNetConfig() {
{
add(0, new HomesteadConfig(easyMiningConst));
add(5, new HomesteadDAOConfig(easyMiningConst, 5, 0x1_000_000_001L, codeHash));
add(5, new HomesteadDAOConfig(easyMiningConst, 5, 0x1_000_000_001L, codeHash, new byte[][] {whiteAddr}));
}
});
}
Expand All @@ -69,6 +76,7 @@ public void testForkAgreed() {
StandaloneBlockchain bc = new StandaloneBlockchain()
.withAutoblock(false);
SolidityContract dao = bc.submitNewContract(daoEmulator, "TestDAO");
SolidityContract white = bc.submitNewContract(daoEmulator, "WhiteHat");
bc.createBlock(); // #1
SolidityContract daoRobber = bc.submitNewContract(daoEmulator, "DAORobber");
bc.sendEther(dao.getAddress(), BigInteger.valueOf(1000));
Expand All @@ -91,10 +99,12 @@ public void testForkAgreed() {
dao.callFunction("withdraw");
bc.createBlock(); // #5 invalid
daoRobber.callFunction("robDao", Hex.toHexString(dao.getAddress()));
bc.createBlock(); // #6 invalid
bc.createBlock();// #6 invalid
white.callFunction("saveDao", Hex.toHexString(dao.getAddress()));
bc.createBlock();// #6 invalid

long balance = bc.getBlockchain().getRepository().getBalance(dao.getAddress()).longValue();
Assert.assertEquals(960, balance);
Assert.assertEquals(950, balance);

for (int i = 0; i < 10; i++) {
dao.callFunction(10, "deposit");
Expand All @@ -109,6 +119,12 @@ public void testForkAgreed() {
bc.createBlock();
Assert.assertEquals(BigInteger.valueOf(balance),
bc.getBlockchain().getRepository().getBalance(dao.getAddress()));

white.callFunction("saveDao", Hex.toHexString(dao.getAddress()));
bc.createBlock();// #6 invalid
balance -= 10;
Assert.assertEquals(BigInteger.valueOf(balance),
bc.getBlockchain().getRepository().getBalance(dao.getAddress()));
}
}

Expand All @@ -118,6 +134,7 @@ public void testForkIgnored() {
.withAutoblock(false)
.withBlockGasIncrease(100);
SolidityContract dao = bc.submitNewContract(daoEmulator, "TestDAO");
SolidityContract white = bc.submitNewContract(daoEmulator, "WhiteHat");
bc.createBlock(); // #1
SolidityContract daoRobber = bc.submitNewContract(daoEmulator, "DAORobber");
bc.sendEther(dao.getAddress(), BigInteger.valueOf(1000));
Expand Down Expand Up @@ -155,6 +172,7 @@ public void testForkUncertain() {
StandaloneBlockchain bc = new StandaloneBlockchain()
.withAutoblock(false);
SolidityContract dao = bc.submitNewContract(daoEmulator, "TestDAO");
SolidityContract white = bc.submitNewContract(daoEmulator, "WhiteHat");
bc.createBlock(); // #1
SolidityContract daoRobber = bc.submitNewContract(daoEmulator, "DAORobber");
bc.sendEther(dao.getAddress(), BigInteger.valueOf(1000));
Expand All @@ -170,23 +188,27 @@ public void testForkUncertain() {

dao.callFunction("withdraw");
daoRobber.callFunction("robDao", Hex.toHexString(dao.getAddress()));
bc.createForkBlock(b5y); // #6 invalid
Block b6y = bc.createForkBlock(b5y);// #6
Assert.assertEquals(BigInteger.valueOf(1000),
bc.getBlockchain().getRepository().getBalance(dao.getAddress()));
white.callFunction("saveDao", Hex.toHexString(dao.getAddress()));
Block b7y = bc.createForkBlock(b6y);// #6
Assert.assertEquals(BigInteger.valueOf(990),
bc.getBlockchain().getRepository().getBalance(dao.getAddress()));

dao.callFunction("withdraw");
daoRobber.callFunction("robDao", Hex.toHexString(dao.getAddress()));
Block b6n = bc.createForkBlock(b5n);// #6'
Block b7n = bc.createForkBlock(b6n); // #7'
Block b8n = bc.createForkBlock(b7n); // #8'
Assert.assertEquals(BigInteger.valueOf(980),
bc.getBlockchain().getRepository().getBalance(dao.getAddress()));


Block b6 = bc.createForkBlock(b5y);// #6
Block b7 = bc.createForkBlock(b6);// #7 (main)
Block b8 = bc.createForkBlock(b7);// #7 (main)
Block b8 = bc.createForkBlock(b7y);// #7 (main)
Block b9 = bc.createForkBlock(b8);// #7 (main)

Assert.assertEquals(BigInteger.valueOf(1000),
Assert.assertEquals(BigInteger.valueOf(990),
bc.getBlockchain().getRepository().getBalance(dao.getAddress()));
}
}

0 comments on commit e63dd90

Please sign in to comment.