From c227476c72479e65c0af5b47d5f55f813c84a1df Mon Sep 17 00:00:00 2001 From: zergweak Date: Wed, 9 May 2018 11:23:51 +0800 Subject: [PATCH 01/17] modify updateaccount and add name validate and add unit test case --- .../core/actuator/UpdateAccountActuator.java | 64 +++++- .../org/tron/core/capsule/AccountCapsule.java | 4 + .../core/capsule/utils/TransactionUtil.java | 18 ++ .../actuator/UpdateAccountActuatorTest.java | 212 ++++++++++++++++++ 4 files changed, 286 insertions(+), 12 deletions(-) create mode 100755 src/test/java/org/tron/core/actuator/UpdateAccountActuatorTest.java diff --git a/src/main/java/org/tron/core/actuator/UpdateAccountActuator.java b/src/main/java/org/tron/core/actuator/UpdateAccountActuator.java index 992bb380814..5d6cbb649af 100644 --- a/src/main/java/org/tron/core/actuator/UpdateAccountActuator.java +++ b/src/main/java/org/tron/core/actuator/UpdateAccountActuator.java @@ -4,42 +4,82 @@ import com.google.protobuf.ByteString; import com.google.protobuf.InvalidProtocolBufferException; import lombok.extern.slf4j.Slf4j; +import org.tron.core.Wallet; import org.tron.core.capsule.AccountCapsule; import org.tron.core.capsule.TransactionResultCapsule; +import org.tron.core.capsule.utils.TransactionUtil; +import org.tron.core.db.AccountStore; import org.tron.core.db.Manager; import org.tron.core.exception.ContractExeException; import org.tron.core.exception.ContractValidateException; import org.tron.protos.Contract.AccountUpdateContract; +import org.tron.protos.Protocol.Transaction.Result.code; @Slf4j public class UpdateAccountActuator extends AbstractActuator { + AccountUpdateContract accountUpdateContract; + byte[] accountName; + byte[] ownerAddress; + long fee; + UpdateAccountActuator(Any contract, Manager dbManager) { super(contract, dbManager); + try { + accountUpdateContract = contract.unpack(AccountUpdateContract.class); + accountName = accountUpdateContract.getAccountName().toByteArray(); + ownerAddress = accountUpdateContract.getOwnerAddress().toByteArray(); + fee = calcFee(); + } catch (InvalidProtocolBufferException e) { + logger.error(e.getMessage(), e); + } catch (Exception e) { + logger.error(e.getMessage(), e); + } } @Override - public boolean execute(TransactionResultCapsule result) throws ContractExeException { - long fee = calcFee(); + public boolean execute(TransactionResultCapsule ret) throws ContractExeException { try { + AccountStore accountStore = dbManager.getAccountStore(); + AccountCapsule account = accountStore.get(ownerAddress); - AccountUpdateContract accountUpdateContract = contract.unpack(AccountUpdateContract.class); - AccountCapsule account = - dbManager.getAccountStore().get(accountUpdateContract.getOwnerAddress().toByteArray()); - - account.setAccountName(accountUpdateContract.getAccountName().toByteArray()); - dbManager.getAccountStore().put(accountUpdateContract.getOwnerAddress().toByteArray(), - account); - return true; - } catch (InvalidProtocolBufferException e) { + account.setAccountName(accountName); + accountStore.put(ownerAddress, account); + ret.setStatus(fee, code.SUCESS); + } catch (Exception e) { logger.debug(e.getMessage(), e); + ret.setStatus(fee, code.FAILED); throw new ContractExeException(e.getMessage()); } + return true; } @Override public boolean validate() throws ContractValidateException { - // todo validate freq. + try { + if (this.dbManager == null) { + throw new ContractValidateException("No dbManager!"); + } + if (accountUpdateContract == null) { + throw new ContractValidateException( + "contract type error,expected type [AccountUpdateContract],real type[" + contract + .getClass() + "]"); + } + + if (!TransactionUtil.validAccountName(accountName)) { + throw new ContractValidateException("Invalidate accountName"); + } + if (!Wallet.addressValid(ownerAddress)) { + throw new ContractValidateException("Invalidate ownerAddress"); + } + //TO do 唯一性校验 + if (!dbManager.getAccountStore().has(ownerAddress)) { + throw new ContractValidateException("Account has not existed"); + } + } catch (Exception ex) { + ex.printStackTrace(); + throw new ContractValidateException(ex.getMessage()); + } return true; } diff --git a/src/main/java/org/tron/core/capsule/AccountCapsule.java b/src/main/java/org/tron/core/capsule/AccountCapsule.java index 06daff0e974..67e3766ca26 100644 --- a/src/main/java/org/tron/core/capsule/AccountCapsule.java +++ b/src/main/java/org/tron/core/capsule/AccountCapsule.java @@ -165,6 +165,10 @@ public AccountType getType() { return this.account.getType(); } + public ByteString getAccountName() { + return this.account.getAccountName(); + } + public long getBalance() { return this.account.getBalance(); diff --git a/src/main/java/org/tron/core/capsule/utils/TransactionUtil.java b/src/main/java/org/tron/core/capsule/utils/TransactionUtil.java index 9e954d6bb74..be2e2b49715 100644 --- a/src/main/java/org/tron/core/capsule/utils/TransactionUtil.java +++ b/src/main/java/org/tron/core/capsule/utils/TransactionUtil.java @@ -49,6 +49,24 @@ private static boolean checkBalance(long totalBalance, long totalSpent) { return totalBalance == totalSpent; } + public static boolean validAccountName(byte[] accountName) { + if (accountName == null || accountName.length == 0) { + return false; + } + if (accountName.length > 32) { + return false; + } + // b must read able. + for (byte b : accountName) { + if (b < 0x21) { + return false; // 0x21 = '!' + } + if (b > 0x7E) { + return false; // 0x7E = '~' + } + } + return true; + } /** * Get sender. */ diff --git a/src/test/java/org/tron/core/actuator/UpdateAccountActuatorTest.java b/src/test/java/org/tron/core/actuator/UpdateAccountActuatorTest.java new file mode 100755 index 00000000000..7cb8d7967fe --- /dev/null +++ b/src/test/java/org/tron/core/actuator/UpdateAccountActuatorTest.java @@ -0,0 +1,212 @@ +package org.tron.core.actuator; + +import com.google.protobuf.Any; +import com.google.protobuf.ByteString; +import java.io.File; +import lombok.extern.slf4j.Slf4j; +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.springframework.context.annotation.AnnotationConfigApplicationContext; +import org.tron.common.utils.ByteArray; +import org.tron.common.utils.FileUtil; +import org.tron.core.Constant; +import org.tron.core.Wallet; +import org.tron.core.capsule.AccountCapsule; +import org.tron.core.capsule.TransactionResultCapsule; +import org.tron.core.config.DefaultConfig; +import org.tron.core.config.args.Args; +import org.tron.core.db.Manager; +import org.tron.core.exception.ContractExeException; +import org.tron.core.exception.ContractValidateException; +import org.tron.protos.Contract; +import org.tron.protos.Protocol.AccountType; +import org.tron.protos.Protocol.Transaction.Result.code; + +@Slf4j +public class UpdateAccountActuatorTest { + + private static AnnotationConfigApplicationContext context; + private static Manager dbManager; + private static Any contract; + private static final String dbPath = "output_CreateAccountTest"; + + private static final String OWNER_ADDRESS_NOT_EXIT = + Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049abc"; + private static final String ACCOUNT_NAME = "ownerTest"; + private static final String OWNER_ADDRESS = + Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d4271a1abc"; + private static final String OWNER_ADDRESS_INVALIATE = "aaaa"; + + static { + Args.setParam(new String[]{"--output-directory", dbPath}, Constant.TEST_CONF); + context = new AnnotationConfigApplicationContext(DefaultConfig.class); + } + + /** + * Init data. + */ + @BeforeClass + public static void init() { + dbManager = context.getBean(Manager.class); + } + + /** + * create temp Capsule test need. + */ + @Before + public void createCapsule() { + AccountCapsule ownerCapsule = + new AccountCapsule( + ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS)), + ByteString.copyFromUtf8(ACCOUNT_NAME), + AccountType.Normal); + dbManager.getAccountStore().put(ownerCapsule.getAddress().toByteArray(), ownerCapsule); + dbManager.getAccountStore().delete(ByteArray.fromHexString(OWNER_ADDRESS_NOT_EXIT)); + } + + private Any getContract(String name, String address) { + return Any.pack( + Contract.AccountUpdateContract.newBuilder() + .setAccountName(ByteString.copyFromUtf8(name)) + .setOwnerAddress(ByteString.copyFrom(ByteArray.fromHexString(address))) + .build()); + } + + private Any getContract(ByteString name, String address) { + return Any.pack( + Contract.AccountUpdateContract.newBuilder() + .setAccountName(name) + .setOwnerAddress(ByteString.copyFrom(ByteArray.fromHexString(address))) + .build()); + } + + /** + * Unit test. + */ + /** + * Update account when all right. + */ + @Test + public void rightUpdateAccount() { + TransactionResultCapsule ret = new TransactionResultCapsule(); + UpdateAccountActuator actuator = new UpdateAccountActuator( + getContract(ACCOUNT_NAME, OWNER_ADDRESS), dbManager); + try { + actuator.validate(); + actuator.execute(ret); + Assert.assertEquals(ret.getInstance().getRet(), code.SUCESS); + AccountCapsule accountCapsule = dbManager.getAccountStore() + .get(ByteArray.fromHexString(OWNER_ADDRESS)); + Assert.assertEquals(ACCOUNT_NAME, accountCapsule.getAccountName().toStringUtf8()); + } catch (ContractValidateException e) { + Assert.assertFalse(e instanceof ContractValidateException); + } catch (ContractExeException e) { + Assert.assertFalse(e instanceof ContractExeException); + } + } + + @Test + public void invalidAddress() { + TransactionResultCapsule ret = new TransactionResultCapsule(); + UpdateAccountActuator actuator = new UpdateAccountActuator( + getContract(ACCOUNT_NAME, OWNER_ADDRESS_INVALIATE), dbManager); + try { + actuator.validate(); + actuator.execute(ret); + } catch (ContractValidateException e) { + Assert.assertTrue(e instanceof ContractValidateException); + Assert.assertEquals("Invalidate ownerAddress", e.getMessage()); + } catch (ContractExeException e) { + Assert.assertFalse(e instanceof ContractExeException); + } + } + + @Test + public void invalidName() { + TransactionResultCapsule ret = new TransactionResultCapsule(); + //Just OK + try { + UpdateAccountActuator actuator = new UpdateAccountActuator( + getContract("testname0123456789abcdefghijgklm", OWNER_ADDRESS), dbManager); + actuator.validate(); + actuator.execute(ret); + Assert.assertEquals(ret.getInstance().getRet(), code.SUCESS); + AccountCapsule accountCapsule = dbManager.getAccountStore() + .get(ByteArray.fromHexString(OWNER_ADDRESS)); + Assert.assertEquals("testname0123456789abcdefghijgklm", accountCapsule.getAccountName().toStringUtf8()); + } catch (ContractValidateException e) { + Assert.assertFalse(e instanceof ContractValidateException); + } catch (ContractExeException e) { + Assert.assertFalse(e instanceof ContractExeException); + } + + //Empty name + try { + UpdateAccountActuator actuator = new UpdateAccountActuator( + getContract(ByteString.EMPTY, OWNER_ADDRESS), dbManager); + actuator.validate(); + actuator.execute(ret); + } catch (ContractValidateException e) { + Assert.assertTrue(e instanceof ContractValidateException); + Assert.assertEquals("Invalidate accountName", e.getMessage()); + } catch (ContractExeException e) { + Assert.assertFalse(e instanceof ContractExeException); + } + + //Too long name + try { + UpdateAccountActuator actuator = new UpdateAccountActuator( + getContract("testname0123456789abcdefghijgklmo", OWNER_ADDRESS), dbManager); + actuator.validate(); + actuator.execute(ret); + } catch (ContractValidateException e) { + Assert.assertTrue(e instanceof ContractValidateException); + Assert.assertEquals("Invalidate accountName", e.getMessage()); + } catch (ContractExeException e) { + Assert.assertFalse(e instanceof ContractExeException); + } + + //Can't contain space + try { + UpdateAccountActuator actuator = new UpdateAccountActuator( + getContract("t e", OWNER_ADDRESS), dbManager); + actuator.validate(); + actuator.execute(ret); + } catch (ContractValidateException e) { + Assert.assertTrue(e instanceof ContractValidateException); + Assert.assertEquals("Invalidate accountName", e.getMessage()); + } catch (ContractExeException e) { + Assert.assertFalse(e instanceof ContractExeException); + } + + //Can't contain chinese characters + try { + UpdateAccountActuator actuator = new UpdateAccountActuator( + getContract("测试", OWNER_ADDRESS), dbManager); + actuator.validate(); + actuator.execute(ret); + } catch (ContractValidateException e) { + Assert.assertTrue(e instanceof ContractValidateException); + Assert.assertEquals("Invalidate accountName", e.getMessage()); + } catch (ContractExeException e) { + Assert.assertFalse(e instanceof ContractExeException); + } + } + + /** + * Release resources. + */ + @AfterClass + public static void destroy() { + Args.clearParam(); + if (FileUtil.deleteDir(new File(dbPath))) { + logger.info("Release resources successful."); + } else { + logger.info("Release resources failure."); + } + context.destroy(); + } +} From 2ebc21767f9ef58bb1bf15bfbfc6a0e9e2d95570 Mon Sep 17 00:00:00 2001 From: Heng Zhang Date: Wed, 9 May 2018 11:33:35 +0800 Subject: [PATCH 02/17] freture:add AccountIndexDtore. --- .../org/tron/core/capsule/AccountCapsule.java | 3 + .../org/tron/core/config/DefaultConfig.java | 5 ++ .../org/tron/core/db/AccountIndexStore.java | 72 +++++++++++++++++++ 3 files changed, 80 insertions(+) create mode 100644 src/main/java/org/tron/core/db/AccountIndexStore.java diff --git a/src/main/java/org/tron/core/capsule/AccountCapsule.java b/src/main/java/org/tron/core/capsule/AccountCapsule.java index 06daff0e974..62a2f7ced15 100644 --- a/src/main/java/org/tron/core/capsule/AccountCapsule.java +++ b/src/main/java/org/tron/core/capsule/AccountCapsule.java @@ -364,4 +364,7 @@ public void setLatestWithdrawTime(long latestWithdrawTime) { .build(); } + public ByteString getName() { + return this.account.getAccountName(); + } } diff --git a/src/main/java/org/tron/core/config/DefaultConfig.java b/src/main/java/org/tron/core/config/DefaultConfig.java index 4d15e1fc21a..6aeef189e7c 100755 --- a/src/main/java/org/tron/core/config/DefaultConfig.java +++ b/src/main/java/org/tron/core/config/DefaultConfig.java @@ -71,6 +71,11 @@ public String blockIndex() { return "block-index"; } + @Bean(name = "account-index") + public String accountIndex() { + return "account-index"; + } + @Bean(name = "witness_schedule") public String witnessSchedule() { return "witness_schedule"; diff --git a/src/main/java/org/tron/core/db/AccountIndexStore.java b/src/main/java/org/tron/core/db/AccountIndexStore.java new file mode 100644 index 00000000000..d1da4e701e4 --- /dev/null +++ b/src/main/java/org/tron/core/db/AccountIndexStore.java @@ -0,0 +1,72 @@ +package org.tron.core.db; + +import org.apache.commons.lang3.ArrayUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.stereotype.Component; +import org.tron.common.utils.ByteArray; +import org.tron.core.capsule.AccountCapsule; +import org.tron.core.capsule.BytesCapsule; +import org.tron.core.exception.ItemNotFoundException; + +@Component +public class AccountIndexStore extends TronStoreWithRevoking { + + + @Autowired + public AccountIndexStore(@Qualifier("account-index") String dbName) { + super(dbName); + + } + + private static AccountIndexStore instance; + + public static void destroy() { + instance = null; + } + + /** + * create fun. + * + * @param dbName the name of database + */ + public static AccountIndexStore create(String dbName) { + if (instance == null) { + synchronized (AccountIndexStore.class) { + if (instance == null) { + instance = new AccountIndexStore(dbName); + } + } + } + return instance; + } + + public void put(AccountCapsule accountCapsule) { + put(accountCapsule.getName().toByteArray(), + new BytesCapsule(accountCapsule.getAddress().toByteArray())); + } + + public byte[] get(String name) + throws ItemNotFoundException { + return get(ByteArray.fromString(name)).getData(); + } + + @Override + public BytesCapsule get(byte[] key) { + byte[] value = dbSource.getData(key); + if (ArrayUtils.isEmpty(value)) { + return null; + } + return new BytesCapsule(value); + } + + + @Override + public boolean has(byte[] key) { + byte[] value = dbSource.getData(key); + if (ArrayUtils.isEmpty(value)) { + return false; + } + return true; + } +} \ No newline at end of file From 516092a10e573d1269906fa4050748999b45b0fb Mon Sep 17 00:00:00 2001 From: zergweak Date: Wed, 9 May 2018 11:40:04 +0800 Subject: [PATCH 03/17] add the local test config file --- src/main/resources/config-localtest.conf | 132 +++++++++++++++++++++++ 1 file changed, 132 insertions(+) create mode 100644 src/main/resources/config-localtest.conf diff --git a/src/main/resources/config-localtest.conf b/src/main/resources/config-localtest.conf new file mode 100644 index 00000000000..e659c5a709c --- /dev/null +++ b/src/main/resources/config-localtest.conf @@ -0,0 +1,132 @@ +net { + # type = mainnet + type = testnet +} + +storage { + # Directory for storing persistent data + directory = "database" +} + +node.discovery = { + enable = true + persist = true + bind.ip = "" + external.ip = null +} + +node { + # trust node for solidity node + trustNode = "47.93.9.236:50051" + + listen.port = 7777 + + connection.timeout = 2 + + active = [ + # Sample entries: + # { url = "enode://@hostname.com:30303" } + # { + # ip = hostname.com + # port = 30303 + # nodeId = e437a4836b77ad9d9ffe73ee782ef2614e6d8370fcf62191a6e488276e23717147073a7ce0b444d485fff5a0c34c4577251a7a990cf80d8542e21b95aa8c5e6c + # } + "127.0.0.1:7777", + "127.0.0.1:8888", + "127.0.0.1:9999", + ] + + maxActiveNodes = 30 + + p2p { + version = 333 # 47: testnet; 101: debug + } + +} + +sync { + node.count = 30 +} + +seed.node = { + # List of the seed nodes + # Seed nodes are stable full nodes + # example: + # ip.list = [ + # "ip:port", + # "ip:port" + # ] + ip.list = [ + "127.0.0.1:7777", + "127.0.0.1:8888", + "127.0.0.1:9999", + ] +} + +genesis.block = { +# Reserve balance + assets = [ + # the account of foundation. + { + accountName = "Zion" + accountType = "AssetIssue" + address = "27XK5sBhwa773Svn9j2Mud6rajxtauEN4tr" + balance = "25000000000000000" + #priKey = D95611A9AF2A2A45359106222ED1AFED48853D9A44DEFF8DC7913F5CBA727366 + #password = 2VYRqa8qKkU1kQYiLtGv7UiFPZpE3v+Nx5E/XLpyc2Y= + }, + + # the account of payment + { + accountName = "Sun" + accountType = "AssetIssue" + address = "27Vm12vh5Mm9HzPSWBDvbZu1U25xvyFvexF" + balance = "10000000000000000" + #priKey = cba92a516ea09f620a16ff7ee95ce0df1d56550a8babe9964981a7144c8a784a + #password = y6kqUW6gn2IKFv9+6Vzg3x1WVQqLq+mWSYGnFEyKeEo= + }, + + # the account of coin burn + { + accountName = "Blackhole" + accountType = "AssetIssue" + address = "27WSAMG2c7LfNM6spu3dVHqGU8zgtEFRafY" + balance = "-9223372036854775808" + #priKey = 8E812436A0E3323166E1F0E8BA79E19E217B2C4A53C970D4CCA0CFB1078979DF + #password = joEkNqDjMjFm4fDounnhniF7LEpTyXDUzKDPsQeJed8= + } + ] + + witnesses = [ + { + address: 27cxdsPw7vmNp5YvXscvC5xhdLeeqbwuX14 + url = "http://Mercury.org", + voteCount = 105 + #priKey = f5583fd20e13073900a513f333ed13db8c9e83e7e3cf37e74adacef96c5afeaa 7777 + }, + { + address: 27TfVERREG3FeWMHEAQ95tWHG4sb3ANn3Qe + url = "http://Venus.org", + voteCount = 104 + #priKey = 9f5c5e48bf87cf92017313082e8cf0f58ccfce423097f0fcebf801695fc99bd4 8888 + }, + { + address: 27b8RUuyZnNPFNZGct2bZkNu9MnGWNAdH3Z + url = "http://Earth.org", + voteCount = 103 + #priKey = 6781f44d9a2083b14fad1702b8e9ba82749162b795e2fc3f136192fc63f80de2 9999 + }, + ] + + timestamp = "0" #2017-8-26 12:00:00 + + parentHash = "0x0000000000000000000000000000000000000000000000000000000000000000" +} + +localwitness = [ + f5583fd20e13073900a513f333ed13db8c9e83e7e3cf37e74adacef96c5afeaa +] + +block = { + needSyncCheck = false # first node : false, other : true +} \ No newline at end of file From f3af1ebff6d6907ff615d52d2a28577f9baf03dc Mon Sep 17 00:00:00 2001 From: zergweak Date: Wed, 9 May 2018 12:25:42 +0800 Subject: [PATCH 04/17] add updateAccount api --- .../java/org/tron/core/services/RpcApiService.java | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/main/java/org/tron/core/services/RpcApiService.java b/src/main/java/org/tron/core/services/RpcApiService.java index f24193f0462..d51ea1e2ccf 100755 --- a/src/main/java/org/tron/core/services/RpcApiService.java +++ b/src/main/java/org/tron/core/services/RpcApiService.java @@ -466,6 +466,20 @@ public void updateWitness(Contract.WitnessUpdateContract request, responseObserver.onCompleted(); } + @Override + public void updateAccount(Contract.AccountUpdateContract request, + StreamObserver responseObserver) { + try { + responseObserver.onNext( + createTransactionCapsule(request, ContractType.AccountUpdateContract).getInstance()); + } catch (ContractValidateException e) { + responseObserver + .onNext(null); + logger.debug("ContractValidateException", e.getMessage()); + } + responseObserver.onCompleted(); + } + @Override public void freezeBalance(Contract.FreezeBalanceContract request, StreamObserver responseObserver) { From b9296ac0b6af251e22e85429284c3ad7cdfd0643 Mon Sep 17 00:00:00 2001 From: zergweak Date: Wed, 9 May 2018 12:36:40 +0800 Subject: [PATCH 05/17] modify getActuatorByContract add AccountUpdateContract case --- src/main/java/org/tron/core/actuator/ActuatorFactory.java | 4 ++-- .../java/org/tron/core/actuator/CreateAccountActuator.java | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/tron/core/actuator/ActuatorFactory.java b/src/main/java/org/tron/core/actuator/ActuatorFactory.java index 51661021851..79d06423372 100644 --- a/src/main/java/org/tron/core/actuator/ActuatorFactory.java +++ b/src/main/java/org/tron/core/actuator/ActuatorFactory.java @@ -41,8 +41,8 @@ public static List createActuator(TransactionCapsule transactionCapsul private static Actuator getActuatorByContract(Contract contract, Manager manager) { switch (contract.getType()) { - case AccountCreateContract: - return new CreateAccountActuator(contract.getParameter(), manager); + case AccountUpdateContract: + return new UpdateAccountActuator(contract.getParameter(), manager); case TransferContract: return new TransferActuator(contract.getParameter(), manager); case TransferAssetContract: diff --git a/src/main/java/org/tron/core/actuator/CreateAccountActuator.java b/src/main/java/org/tron/core/actuator/CreateAccountActuator.java index 2ee755e182e..109e10f0921 100755 --- a/src/main/java/org/tron/core/actuator/CreateAccountActuator.java +++ b/src/main/java/org/tron/core/actuator/CreateAccountActuator.java @@ -17,7 +17,7 @@ @Slf4j public class CreateAccountActuator extends AbstractActuator { - + @Deprecated //Can not create account by api. Need send more than 1 trx , will create account if not exit. CreateAccountActuator(Any contract, Manager dbManager) { super(contract, dbManager); } From dc82e3480c6b83c513179551f470b5168c78618b Mon Sep 17 00:00:00 2001 From: Heng Zhang Date: Wed, 9 May 2018 12:36:58 +0800 Subject: [PATCH 06/17] test:add AccountIndexDtoreTest. --- .../org/tron/core/db/AccountIndexStore.java | 13 ++- .../tron/core/db/AccountIndexStoreTest.java | 105 ++++++++++++++++++ 2 files changed, 113 insertions(+), 5 deletions(-) create mode 100644 src/test/java/org/tron/core/db/AccountIndexStoreTest.java diff --git a/src/main/java/org/tron/core/db/AccountIndexStore.java b/src/main/java/org/tron/core/db/AccountIndexStore.java index d1da4e701e4..4ac24e60756 100644 --- a/src/main/java/org/tron/core/db/AccountIndexStore.java +++ b/src/main/java/org/tron/core/db/AccountIndexStore.java @@ -1,13 +1,13 @@ package org.tron.core.db; +import com.google.protobuf.ByteString; +import java.util.Objects; import org.apache.commons.lang3.ArrayUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Component; -import org.tron.common.utils.ByteArray; import org.tron.core.capsule.AccountCapsule; import org.tron.core.capsule.BytesCapsule; -import org.tron.core.exception.ItemNotFoundException; @Component public class AccountIndexStore extends TronStoreWithRevoking { @@ -46,9 +46,12 @@ public void put(AccountCapsule accountCapsule) { new BytesCapsule(accountCapsule.getAddress().toByteArray())); } - public byte[] get(String name) - throws ItemNotFoundException { - return get(ByteArray.fromString(name)).getData(); + public byte[] get(ByteString name) { + BytesCapsule bytesCapsule = get(name.toByteArray()); + if (Objects.nonNull(bytesCapsule)) { + return bytesCapsule.getData(); + } + return null; } @Override diff --git a/src/test/java/org/tron/core/db/AccountIndexStoreTest.java b/src/test/java/org/tron/core/db/AccountIndexStoreTest.java new file mode 100644 index 00000000000..0804df93299 --- /dev/null +++ b/src/test/java/org/tron/core/db/AccountIndexStoreTest.java @@ -0,0 +1,105 @@ +package org.tron.core.db; + +import com.google.protobuf.ByteString; +import java.io.File; +import java.util.Random; +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; +import org.springframework.context.annotation.AnnotationConfigApplicationContext; +import org.tron.common.utils.FileUtil; +import org.tron.core.Constant; +import org.tron.core.capsule.AccountCapsule; +import org.tron.core.config.DefaultConfig; +import org.tron.core.config.args.Args; +import org.tron.protos.Protocol.AccountType; + +public class AccountIndexStoreTest { + + private static String dbPath = "output_AccountIndexStore_test"; + private static AnnotationConfigApplicationContext context; + private static AccountIndexStore accountIndexStore; + private static final byte[] ACCOUNT_ADDRESS_ONE = randomBytes(16); + private static final byte[] ACCOUNT_ADDRESS_TWO = randomBytes(16); + private static final byte[] ACCOUNT_ADDRESS_THREE = randomBytes(16); + private static final byte[] ACCOUNT_ADDRESS_FOUR = randomBytes(16); + private static final byte[] ACCOUNT_NAME_ONE = randomBytes(6); + private static final byte[] ACCOUNT_NAME_TWO = randomBytes(6); + private static final byte[] ACCOUNT_NAME_THREE = randomBytes(6); + private static final byte[] ACCOUNT_NAME_FOUR = randomBytes(6); + private static final byte[] ACCOUNT_NAME_FIVE = randomBytes(6); + private static AccountCapsule accountCapsule1; + private static AccountCapsule accountCapsule2; + private static AccountCapsule accountCapsule3; + private static AccountCapsule accountCapsule4; + + static { + Args.setParam(new String[]{"--output-directory", dbPath}, + Constant.TEST_CONF); + context = new AnnotationConfigApplicationContext(DefaultConfig.class); + } + + + @AfterClass + public static void destroy() { + Args.clearParam(); + FileUtil.deleteDir(new File(dbPath)); + context.destroy(); + } + + @BeforeClass + public static void init() { + accountIndexStore = context.getBean(AccountIndexStore.class); + accountCapsule1 = new AccountCapsule(ByteString.copyFrom(ACCOUNT_ADDRESS_ONE), + ByteString.copyFrom(ACCOUNT_NAME_ONE), AccountType.Normal); + accountCapsule2 = new AccountCapsule(ByteString.copyFrom(ACCOUNT_ADDRESS_TWO), + ByteString.copyFrom(ACCOUNT_NAME_TWO), AccountType.Normal); + accountCapsule3 = new AccountCapsule(ByteString.copyFrom(ACCOUNT_ADDRESS_THREE), + ByteString.copyFrom(ACCOUNT_NAME_THREE), AccountType.Normal); + accountCapsule4 = new AccountCapsule(ByteString.copyFrom(ACCOUNT_ADDRESS_FOUR), + ByteString.copyFrom(ACCOUNT_NAME_FOUR), AccountType.Normal); + accountIndexStore.put(accountCapsule1); + accountIndexStore.put(accountCapsule2); + accountIndexStore.put(accountCapsule3); + accountIndexStore.put(accountCapsule4); + } + + + @Test + public void putAndGet() { + byte[] address = accountIndexStore.get(ByteString.copyFrom(ACCOUNT_NAME_ONE)); + Assert.assertArrayEquals("putAndGet1", address, ACCOUNT_ADDRESS_ONE); + address = accountIndexStore.get(ByteString.copyFrom(ACCOUNT_NAME_TWO)); + Assert.assertArrayEquals("putAndGet2", address, ACCOUNT_ADDRESS_TWO); + address = accountIndexStore.get(ByteString.copyFrom(ACCOUNT_NAME_THREE)); + Assert.assertArrayEquals("putAndGet3", address, ACCOUNT_ADDRESS_THREE); + address = accountIndexStore.get(ByteString.copyFrom(ACCOUNT_NAME_FOUR)); + Assert.assertArrayEquals("putAndGet4", address, ACCOUNT_ADDRESS_FOUR); + address = accountIndexStore.get(ByteString.copyFrom(ACCOUNT_NAME_FIVE)); + Assert.assertNull("putAndGet4", address); + + } + + @Test + public void putAndHas() { + Boolean result = accountIndexStore.has(ACCOUNT_NAME_ONE); + Assert.assertTrue("putAndGet1", result); + result = accountIndexStore.has(ACCOUNT_NAME_TWO); + Assert.assertTrue("putAndGet2", result); + result = accountIndexStore.has(ACCOUNT_NAME_THREE); + Assert.assertTrue("putAndGet3", result); + result = accountIndexStore.has(ACCOUNT_NAME_FOUR); + Assert.assertTrue("putAndGet4", result); + result = accountIndexStore.has(ACCOUNT_NAME_FIVE); + Assert.assertFalse("putAndGet4", result); + } + + public static byte[] randomBytes(int length) { + // generate the random number + byte[] result = new byte[length]; + new Random().nextBytes(result); + result[0] = Constant.ADD_PRE_FIX_BYTE_TESTNET; + return result; + } +} \ No newline at end of file From 932713961bb80db14c3d118e160dd19b67be07a3 Mon Sep 17 00:00:00 2001 From: zergweak Date: Wed, 9 May 2018 11:23:51 +0800 Subject: [PATCH 07/17] modify updateaccount and add name validate and add unit test case --- .../core/actuator/UpdateAccountActuator.java | 64 +++++- .../org/tron/core/capsule/AccountCapsule.java | 4 + .../core/capsule/utils/TransactionUtil.java | 18 ++ .../actuator/UpdateAccountActuatorTest.java | 212 ++++++++++++++++++ 4 files changed, 286 insertions(+), 12 deletions(-) create mode 100755 src/test/java/org/tron/core/actuator/UpdateAccountActuatorTest.java diff --git a/src/main/java/org/tron/core/actuator/UpdateAccountActuator.java b/src/main/java/org/tron/core/actuator/UpdateAccountActuator.java index 992bb380814..5d6cbb649af 100644 --- a/src/main/java/org/tron/core/actuator/UpdateAccountActuator.java +++ b/src/main/java/org/tron/core/actuator/UpdateAccountActuator.java @@ -4,42 +4,82 @@ import com.google.protobuf.ByteString; import com.google.protobuf.InvalidProtocolBufferException; import lombok.extern.slf4j.Slf4j; +import org.tron.core.Wallet; import org.tron.core.capsule.AccountCapsule; import org.tron.core.capsule.TransactionResultCapsule; +import org.tron.core.capsule.utils.TransactionUtil; +import org.tron.core.db.AccountStore; import org.tron.core.db.Manager; import org.tron.core.exception.ContractExeException; import org.tron.core.exception.ContractValidateException; import org.tron.protos.Contract.AccountUpdateContract; +import org.tron.protos.Protocol.Transaction.Result.code; @Slf4j public class UpdateAccountActuator extends AbstractActuator { + AccountUpdateContract accountUpdateContract; + byte[] accountName; + byte[] ownerAddress; + long fee; + UpdateAccountActuator(Any contract, Manager dbManager) { super(contract, dbManager); + try { + accountUpdateContract = contract.unpack(AccountUpdateContract.class); + accountName = accountUpdateContract.getAccountName().toByteArray(); + ownerAddress = accountUpdateContract.getOwnerAddress().toByteArray(); + fee = calcFee(); + } catch (InvalidProtocolBufferException e) { + logger.error(e.getMessage(), e); + } catch (Exception e) { + logger.error(e.getMessage(), e); + } } @Override - public boolean execute(TransactionResultCapsule result) throws ContractExeException { - long fee = calcFee(); + public boolean execute(TransactionResultCapsule ret) throws ContractExeException { try { + AccountStore accountStore = dbManager.getAccountStore(); + AccountCapsule account = accountStore.get(ownerAddress); - AccountUpdateContract accountUpdateContract = contract.unpack(AccountUpdateContract.class); - AccountCapsule account = - dbManager.getAccountStore().get(accountUpdateContract.getOwnerAddress().toByteArray()); - - account.setAccountName(accountUpdateContract.getAccountName().toByteArray()); - dbManager.getAccountStore().put(accountUpdateContract.getOwnerAddress().toByteArray(), - account); - return true; - } catch (InvalidProtocolBufferException e) { + account.setAccountName(accountName); + accountStore.put(ownerAddress, account); + ret.setStatus(fee, code.SUCESS); + } catch (Exception e) { logger.debug(e.getMessage(), e); + ret.setStatus(fee, code.FAILED); throw new ContractExeException(e.getMessage()); } + return true; } @Override public boolean validate() throws ContractValidateException { - // todo validate freq. + try { + if (this.dbManager == null) { + throw new ContractValidateException("No dbManager!"); + } + if (accountUpdateContract == null) { + throw new ContractValidateException( + "contract type error,expected type [AccountUpdateContract],real type[" + contract + .getClass() + "]"); + } + + if (!TransactionUtil.validAccountName(accountName)) { + throw new ContractValidateException("Invalidate accountName"); + } + if (!Wallet.addressValid(ownerAddress)) { + throw new ContractValidateException("Invalidate ownerAddress"); + } + //TO do 唯一性校验 + if (!dbManager.getAccountStore().has(ownerAddress)) { + throw new ContractValidateException("Account has not existed"); + } + } catch (Exception ex) { + ex.printStackTrace(); + throw new ContractValidateException(ex.getMessage()); + } return true; } diff --git a/src/main/java/org/tron/core/capsule/AccountCapsule.java b/src/main/java/org/tron/core/capsule/AccountCapsule.java index 62a2f7ced15..bf574cbcf72 100644 --- a/src/main/java/org/tron/core/capsule/AccountCapsule.java +++ b/src/main/java/org/tron/core/capsule/AccountCapsule.java @@ -165,6 +165,10 @@ public AccountType getType() { return this.account.getType(); } + public ByteString getAccountName() { + return this.account.getAccountName(); + } + public long getBalance() { return this.account.getBalance(); diff --git a/src/main/java/org/tron/core/capsule/utils/TransactionUtil.java b/src/main/java/org/tron/core/capsule/utils/TransactionUtil.java index 9e954d6bb74..be2e2b49715 100644 --- a/src/main/java/org/tron/core/capsule/utils/TransactionUtil.java +++ b/src/main/java/org/tron/core/capsule/utils/TransactionUtil.java @@ -49,6 +49,24 @@ private static boolean checkBalance(long totalBalance, long totalSpent) { return totalBalance == totalSpent; } + public static boolean validAccountName(byte[] accountName) { + if (accountName == null || accountName.length == 0) { + return false; + } + if (accountName.length > 32) { + return false; + } + // b must read able. + for (byte b : accountName) { + if (b < 0x21) { + return false; // 0x21 = '!' + } + if (b > 0x7E) { + return false; // 0x7E = '~' + } + } + return true; + } /** * Get sender. */ diff --git a/src/test/java/org/tron/core/actuator/UpdateAccountActuatorTest.java b/src/test/java/org/tron/core/actuator/UpdateAccountActuatorTest.java new file mode 100755 index 00000000000..7cb8d7967fe --- /dev/null +++ b/src/test/java/org/tron/core/actuator/UpdateAccountActuatorTest.java @@ -0,0 +1,212 @@ +package org.tron.core.actuator; + +import com.google.protobuf.Any; +import com.google.protobuf.ByteString; +import java.io.File; +import lombok.extern.slf4j.Slf4j; +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.springframework.context.annotation.AnnotationConfigApplicationContext; +import org.tron.common.utils.ByteArray; +import org.tron.common.utils.FileUtil; +import org.tron.core.Constant; +import org.tron.core.Wallet; +import org.tron.core.capsule.AccountCapsule; +import org.tron.core.capsule.TransactionResultCapsule; +import org.tron.core.config.DefaultConfig; +import org.tron.core.config.args.Args; +import org.tron.core.db.Manager; +import org.tron.core.exception.ContractExeException; +import org.tron.core.exception.ContractValidateException; +import org.tron.protos.Contract; +import org.tron.protos.Protocol.AccountType; +import org.tron.protos.Protocol.Transaction.Result.code; + +@Slf4j +public class UpdateAccountActuatorTest { + + private static AnnotationConfigApplicationContext context; + private static Manager dbManager; + private static Any contract; + private static final String dbPath = "output_CreateAccountTest"; + + private static final String OWNER_ADDRESS_NOT_EXIT = + Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049abc"; + private static final String ACCOUNT_NAME = "ownerTest"; + private static final String OWNER_ADDRESS = + Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d4271a1abc"; + private static final String OWNER_ADDRESS_INVALIATE = "aaaa"; + + static { + Args.setParam(new String[]{"--output-directory", dbPath}, Constant.TEST_CONF); + context = new AnnotationConfigApplicationContext(DefaultConfig.class); + } + + /** + * Init data. + */ + @BeforeClass + public static void init() { + dbManager = context.getBean(Manager.class); + } + + /** + * create temp Capsule test need. + */ + @Before + public void createCapsule() { + AccountCapsule ownerCapsule = + new AccountCapsule( + ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS)), + ByteString.copyFromUtf8(ACCOUNT_NAME), + AccountType.Normal); + dbManager.getAccountStore().put(ownerCapsule.getAddress().toByteArray(), ownerCapsule); + dbManager.getAccountStore().delete(ByteArray.fromHexString(OWNER_ADDRESS_NOT_EXIT)); + } + + private Any getContract(String name, String address) { + return Any.pack( + Contract.AccountUpdateContract.newBuilder() + .setAccountName(ByteString.copyFromUtf8(name)) + .setOwnerAddress(ByteString.copyFrom(ByteArray.fromHexString(address))) + .build()); + } + + private Any getContract(ByteString name, String address) { + return Any.pack( + Contract.AccountUpdateContract.newBuilder() + .setAccountName(name) + .setOwnerAddress(ByteString.copyFrom(ByteArray.fromHexString(address))) + .build()); + } + + /** + * Unit test. + */ + /** + * Update account when all right. + */ + @Test + public void rightUpdateAccount() { + TransactionResultCapsule ret = new TransactionResultCapsule(); + UpdateAccountActuator actuator = new UpdateAccountActuator( + getContract(ACCOUNT_NAME, OWNER_ADDRESS), dbManager); + try { + actuator.validate(); + actuator.execute(ret); + Assert.assertEquals(ret.getInstance().getRet(), code.SUCESS); + AccountCapsule accountCapsule = dbManager.getAccountStore() + .get(ByteArray.fromHexString(OWNER_ADDRESS)); + Assert.assertEquals(ACCOUNT_NAME, accountCapsule.getAccountName().toStringUtf8()); + } catch (ContractValidateException e) { + Assert.assertFalse(e instanceof ContractValidateException); + } catch (ContractExeException e) { + Assert.assertFalse(e instanceof ContractExeException); + } + } + + @Test + public void invalidAddress() { + TransactionResultCapsule ret = new TransactionResultCapsule(); + UpdateAccountActuator actuator = new UpdateAccountActuator( + getContract(ACCOUNT_NAME, OWNER_ADDRESS_INVALIATE), dbManager); + try { + actuator.validate(); + actuator.execute(ret); + } catch (ContractValidateException e) { + Assert.assertTrue(e instanceof ContractValidateException); + Assert.assertEquals("Invalidate ownerAddress", e.getMessage()); + } catch (ContractExeException e) { + Assert.assertFalse(e instanceof ContractExeException); + } + } + + @Test + public void invalidName() { + TransactionResultCapsule ret = new TransactionResultCapsule(); + //Just OK + try { + UpdateAccountActuator actuator = new UpdateAccountActuator( + getContract("testname0123456789abcdefghijgklm", OWNER_ADDRESS), dbManager); + actuator.validate(); + actuator.execute(ret); + Assert.assertEquals(ret.getInstance().getRet(), code.SUCESS); + AccountCapsule accountCapsule = dbManager.getAccountStore() + .get(ByteArray.fromHexString(OWNER_ADDRESS)); + Assert.assertEquals("testname0123456789abcdefghijgklm", accountCapsule.getAccountName().toStringUtf8()); + } catch (ContractValidateException e) { + Assert.assertFalse(e instanceof ContractValidateException); + } catch (ContractExeException e) { + Assert.assertFalse(e instanceof ContractExeException); + } + + //Empty name + try { + UpdateAccountActuator actuator = new UpdateAccountActuator( + getContract(ByteString.EMPTY, OWNER_ADDRESS), dbManager); + actuator.validate(); + actuator.execute(ret); + } catch (ContractValidateException e) { + Assert.assertTrue(e instanceof ContractValidateException); + Assert.assertEquals("Invalidate accountName", e.getMessage()); + } catch (ContractExeException e) { + Assert.assertFalse(e instanceof ContractExeException); + } + + //Too long name + try { + UpdateAccountActuator actuator = new UpdateAccountActuator( + getContract("testname0123456789abcdefghijgklmo", OWNER_ADDRESS), dbManager); + actuator.validate(); + actuator.execute(ret); + } catch (ContractValidateException e) { + Assert.assertTrue(e instanceof ContractValidateException); + Assert.assertEquals("Invalidate accountName", e.getMessage()); + } catch (ContractExeException e) { + Assert.assertFalse(e instanceof ContractExeException); + } + + //Can't contain space + try { + UpdateAccountActuator actuator = new UpdateAccountActuator( + getContract("t e", OWNER_ADDRESS), dbManager); + actuator.validate(); + actuator.execute(ret); + } catch (ContractValidateException e) { + Assert.assertTrue(e instanceof ContractValidateException); + Assert.assertEquals("Invalidate accountName", e.getMessage()); + } catch (ContractExeException e) { + Assert.assertFalse(e instanceof ContractExeException); + } + + //Can't contain chinese characters + try { + UpdateAccountActuator actuator = new UpdateAccountActuator( + getContract("测试", OWNER_ADDRESS), dbManager); + actuator.validate(); + actuator.execute(ret); + } catch (ContractValidateException e) { + Assert.assertTrue(e instanceof ContractValidateException); + Assert.assertEquals("Invalidate accountName", e.getMessage()); + } catch (ContractExeException e) { + Assert.assertFalse(e instanceof ContractExeException); + } + } + + /** + * Release resources. + */ + @AfterClass + public static void destroy() { + Args.clearParam(); + if (FileUtil.deleteDir(new File(dbPath))) { + logger.info("Release resources successful."); + } else { + logger.info("Release resources failure."); + } + context.destroy(); + } +} From dfab4c07c07069f28daa2152aae9e3fa9bdaa3d0 Mon Sep 17 00:00:00 2001 From: zergweak Date: Wed, 9 May 2018 11:40:04 +0800 Subject: [PATCH 08/17] add the local test config file --- src/main/resources/config-localtest.conf | 132 +++++++++++++++++++++++ 1 file changed, 132 insertions(+) create mode 100644 src/main/resources/config-localtest.conf diff --git a/src/main/resources/config-localtest.conf b/src/main/resources/config-localtest.conf new file mode 100644 index 00000000000..e659c5a709c --- /dev/null +++ b/src/main/resources/config-localtest.conf @@ -0,0 +1,132 @@ +net { + # type = mainnet + type = testnet +} + +storage { + # Directory for storing persistent data + directory = "database" +} + +node.discovery = { + enable = true + persist = true + bind.ip = "" + external.ip = null +} + +node { + # trust node for solidity node + trustNode = "47.93.9.236:50051" + + listen.port = 7777 + + connection.timeout = 2 + + active = [ + # Sample entries: + # { url = "enode://@hostname.com:30303" } + # { + # ip = hostname.com + # port = 30303 + # nodeId = e437a4836b77ad9d9ffe73ee782ef2614e6d8370fcf62191a6e488276e23717147073a7ce0b444d485fff5a0c34c4577251a7a990cf80d8542e21b95aa8c5e6c + # } + "127.0.0.1:7777", + "127.0.0.1:8888", + "127.0.0.1:9999", + ] + + maxActiveNodes = 30 + + p2p { + version = 333 # 47: testnet; 101: debug + } + +} + +sync { + node.count = 30 +} + +seed.node = { + # List of the seed nodes + # Seed nodes are stable full nodes + # example: + # ip.list = [ + # "ip:port", + # "ip:port" + # ] + ip.list = [ + "127.0.0.1:7777", + "127.0.0.1:8888", + "127.0.0.1:9999", + ] +} + +genesis.block = { +# Reserve balance + assets = [ + # the account of foundation. + { + accountName = "Zion" + accountType = "AssetIssue" + address = "27XK5sBhwa773Svn9j2Mud6rajxtauEN4tr" + balance = "25000000000000000" + #priKey = D95611A9AF2A2A45359106222ED1AFED48853D9A44DEFF8DC7913F5CBA727366 + #password = 2VYRqa8qKkU1kQYiLtGv7UiFPZpE3v+Nx5E/XLpyc2Y= + }, + + # the account of payment + { + accountName = "Sun" + accountType = "AssetIssue" + address = "27Vm12vh5Mm9HzPSWBDvbZu1U25xvyFvexF" + balance = "10000000000000000" + #priKey = cba92a516ea09f620a16ff7ee95ce0df1d56550a8babe9964981a7144c8a784a + #password = y6kqUW6gn2IKFv9+6Vzg3x1WVQqLq+mWSYGnFEyKeEo= + }, + + # the account of coin burn + { + accountName = "Blackhole" + accountType = "AssetIssue" + address = "27WSAMG2c7LfNM6spu3dVHqGU8zgtEFRafY" + balance = "-9223372036854775808" + #priKey = 8E812436A0E3323166E1F0E8BA79E19E217B2C4A53C970D4CCA0CFB1078979DF + #password = joEkNqDjMjFm4fDounnhniF7LEpTyXDUzKDPsQeJed8= + } + ] + + witnesses = [ + { + address: 27cxdsPw7vmNp5YvXscvC5xhdLeeqbwuX14 + url = "http://Mercury.org", + voteCount = 105 + #priKey = f5583fd20e13073900a513f333ed13db8c9e83e7e3cf37e74adacef96c5afeaa 7777 + }, + { + address: 27TfVERREG3FeWMHEAQ95tWHG4sb3ANn3Qe + url = "http://Venus.org", + voteCount = 104 + #priKey = 9f5c5e48bf87cf92017313082e8cf0f58ccfce423097f0fcebf801695fc99bd4 8888 + }, + { + address: 27b8RUuyZnNPFNZGct2bZkNu9MnGWNAdH3Z + url = "http://Earth.org", + voteCount = 103 + #priKey = 6781f44d9a2083b14fad1702b8e9ba82749162b795e2fc3f136192fc63f80de2 9999 + }, + ] + + timestamp = "0" #2017-8-26 12:00:00 + + parentHash = "0x0000000000000000000000000000000000000000000000000000000000000000" +} + +localwitness = [ + f5583fd20e13073900a513f333ed13db8c9e83e7e3cf37e74adacef96c5afeaa +] + +block = { + needSyncCheck = false # first node : false, other : true +} \ No newline at end of file From 1e88f49149912d882e8b18bb1b36e31f752201a8 Mon Sep 17 00:00:00 2001 From: zergweak Date: Wed, 9 May 2018 12:25:42 +0800 Subject: [PATCH 09/17] add updateAccount api --- .../java/org/tron/core/services/RpcApiService.java | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/main/java/org/tron/core/services/RpcApiService.java b/src/main/java/org/tron/core/services/RpcApiService.java index f24193f0462..d51ea1e2ccf 100755 --- a/src/main/java/org/tron/core/services/RpcApiService.java +++ b/src/main/java/org/tron/core/services/RpcApiService.java @@ -466,6 +466,20 @@ public void updateWitness(Contract.WitnessUpdateContract request, responseObserver.onCompleted(); } + @Override + public void updateAccount(Contract.AccountUpdateContract request, + StreamObserver responseObserver) { + try { + responseObserver.onNext( + createTransactionCapsule(request, ContractType.AccountUpdateContract).getInstance()); + } catch (ContractValidateException e) { + responseObserver + .onNext(null); + logger.debug("ContractValidateException", e.getMessage()); + } + responseObserver.onCompleted(); + } + @Override public void freezeBalance(Contract.FreezeBalanceContract request, StreamObserver responseObserver) { From a5c85d64b4f2c437e2a4bed5dde8ca209ee8b6fd Mon Sep 17 00:00:00 2001 From: zergweak Date: Wed, 9 May 2018 12:36:40 +0800 Subject: [PATCH 10/17] modify getActuatorByContract add AccountUpdateContract case --- src/main/java/org/tron/core/actuator/ActuatorFactory.java | 4 ++-- .../java/org/tron/core/actuator/CreateAccountActuator.java | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/tron/core/actuator/ActuatorFactory.java b/src/main/java/org/tron/core/actuator/ActuatorFactory.java index 51661021851..79d06423372 100644 --- a/src/main/java/org/tron/core/actuator/ActuatorFactory.java +++ b/src/main/java/org/tron/core/actuator/ActuatorFactory.java @@ -41,8 +41,8 @@ public static List createActuator(TransactionCapsule transactionCapsul private static Actuator getActuatorByContract(Contract contract, Manager manager) { switch (contract.getType()) { - case AccountCreateContract: - return new CreateAccountActuator(contract.getParameter(), manager); + case AccountUpdateContract: + return new UpdateAccountActuator(contract.getParameter(), manager); case TransferContract: return new TransferActuator(contract.getParameter(), manager); case TransferAssetContract: diff --git a/src/main/java/org/tron/core/actuator/CreateAccountActuator.java b/src/main/java/org/tron/core/actuator/CreateAccountActuator.java index 2ee755e182e..109e10f0921 100755 --- a/src/main/java/org/tron/core/actuator/CreateAccountActuator.java +++ b/src/main/java/org/tron/core/actuator/CreateAccountActuator.java @@ -17,7 +17,7 @@ @Slf4j public class CreateAccountActuator extends AbstractActuator { - + @Deprecated //Can not create account by api. Need send more than 1 trx , will create account if not exit. CreateAccountActuator(Any contract, Manager dbManager) { super(contract, dbManager); } From cb70b8806615ec124dd6a87877542234def58a2f Mon Sep 17 00:00:00 2001 From: zergweak Date: Wed, 9 May 2018 12:51:19 +0800 Subject: [PATCH 11/17] fix a bug: getOwner for AccountUpdateContract --- src/main/java/org/tron/core/capsule/TransactionCapsule.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/tron/core/capsule/TransactionCapsule.java b/src/main/java/org/tron/core/capsule/TransactionCapsule.java index 52038ad3887..673e17d78e6 100755 --- a/src/main/java/org/tron/core/capsule/TransactionCapsule.java +++ b/src/main/java/org/tron/core/capsule/TransactionCapsule.java @@ -37,10 +37,9 @@ import org.tron.common.utils.Sha256Hash; import org.tron.core.Wallet; import org.tron.core.db.AccountStore; -import org.tron.core.exception.ValidateBandwidthException; import org.tron.core.exception.ValidateSignatureException; -import org.tron.protos.Contract.AccountUpdateContract; import org.tron.protos.Contract.AccountCreateContract; +import org.tron.protos.Contract.AccountUpdateContract; import org.tron.protos.Contract.FreezeBalanceContract; import org.tron.protos.Contract.ParticipateAssetIssueContract; import org.tron.protos.Contract.TransferAssetContract; @@ -257,7 +256,7 @@ public static byte[] getOwner(Transaction.Contract contract) { owner = contractParameter.unpack(ParticipateAssetIssueContract.class).getOwnerAddress(); break; case AccountUpdateContract: - owner = contractParameter.unpack(WitnessUpdateContract.class).getOwnerAddress(); + owner = contractParameter.unpack(AccountUpdateContract.class).getOwnerAddress(); break; case FreezeBalanceContract: owner = contractParameter.unpack(FreezeBalanceContract.class).getOwnerAddress(); From 9dfb79d9788a77e8fb1d098710f060efb82e81ca Mon Sep 17 00:00:00 2001 From: Heng Zhang Date: Wed, 9 May 2018 12:55:09 +0800 Subject: [PATCH 12/17] feature:add AccountIndexStore in Manager. --- src/main/java/org/tron/core/db/Manager.java | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/tron/core/db/Manager.java b/src/main/java/org/tron/core/db/Manager.java index 90f73428e90..fad5459bcb9 100644 --- a/src/main/java/org/tron/core/db/Manager.java +++ b/src/main/java/org/tron/core/db/Manager.java @@ -84,6 +84,8 @@ public class Manager { @Autowired private BlockIndexStore blockIndexStore; @Autowired + private AccountIndexStore accountIndexStore; + @Autowired private WitnessScheduleStore witnessScheduleStore; @Autowired private RecentBlockStore recentBlockStore; @@ -231,6 +233,7 @@ public void destory() { DynamicPropertiesStore.destroy(); WitnessScheduleStore.destroy(); BlockIndexStore.destroy(); + AccountIndexStore.destroy(); } @PostConstruct @@ -752,7 +755,8 @@ public LinkedList getBlockChainHashesOnFork(final BlockId forkBlockHash */ public boolean containBlock(final Sha256Hash blockHash) { try { - return this.khaosDb.containBlockInMiniStore(blockHash) || blockStore.get(blockHash.getBytes()) != null; + return this.khaosDb.containBlockInMiniStore(blockHash) + || blockStore.get(blockHash.getBytes()) != null; } catch (ItemNotFoundException e) { return false; } catch (BadItemException e) { @@ -1009,10 +1013,10 @@ public long getSyncBeginNumber() { } public BlockId getSolidBlockId() { - try{ + try { long num = dynamicPropertiesStore.getLatestSolidifiedBlockNum(); return getBlockIdByNum(num); - }catch (Exception e){ + } catch (Exception e) { return getGenesisBlockId(); } } @@ -1103,11 +1107,20 @@ public void setBlockIndexStore(BlockIndexStore indexStore) { this.blockIndexStore = indexStore; } + public AccountIndexStore getAccountIndexStore() { + return this.accountIndexStore; + } + + public void setAccountIndexStore(AccountIndexStore indexStore) { + this.accountIndexStore = indexStore; + } + public void closeAllStore() { System.err.println("******** begin to close db ********"); closeOneStore(accountStore); closeOneStore(blockStore); closeOneStore(blockIndexStore); + closeOneStore(accountIndexStore); closeOneStore(witnessStore); closeOneStore(witnessScheduleStore); closeOneStore(assetIssueStore); From def71bf1743e451aa562ef3195c67084841ebf9d Mon Sep 17 00:00:00 2001 From: zergweak Date: Wed, 9 May 2018 16:21:09 +0800 Subject: [PATCH 13/17] add uniqueness check for account name --- .../core/actuator/UpdateAccountActuator.java | 15 ++- src/main/java/org/tron/core/db/Manager.java | 1 + .../actuator/UpdateAccountActuatorTest.java | 120 +++++++++++++++++- 3 files changed, 129 insertions(+), 7 deletions(-) diff --git a/src/main/java/org/tron/core/actuator/UpdateAccountActuator.java b/src/main/java/org/tron/core/actuator/UpdateAccountActuator.java index 5d6cbb649af..761a03c69ed 100644 --- a/src/main/java/org/tron/core/actuator/UpdateAccountActuator.java +++ b/src/main/java/org/tron/core/actuator/UpdateAccountActuator.java @@ -8,6 +8,7 @@ import org.tron.core.capsule.AccountCapsule; import org.tron.core.capsule.TransactionResultCapsule; import org.tron.core.capsule.utils.TransactionUtil; +import org.tron.core.db.AccountIndexStore; import org.tron.core.db.AccountStore; import org.tron.core.db.Manager; import org.tron.core.exception.ContractExeException; @@ -41,10 +42,13 @@ public class UpdateAccountActuator extends AbstractActuator { public boolean execute(TransactionResultCapsule ret) throws ContractExeException { try { AccountStore accountStore = dbManager.getAccountStore(); + AccountIndexStore accountIndexStore = dbManager.getAccountIndexStore(); AccountCapsule account = accountStore.get(ownerAddress); account.setAccountName(accountName); accountStore.put(ownerAddress, account); + accountIndexStore.put(account); + ret.setStatus(fee, code.SUCESS); } catch (Exception e) { logger.debug(e.getMessage(), e); @@ -72,10 +76,17 @@ public boolean validate() throws ContractValidateException { if (!Wallet.addressValid(ownerAddress)) { throw new ContractValidateException("Invalidate ownerAddress"); } - //TO do 唯一性校验 - if (!dbManager.getAccountStore().has(ownerAddress)) { + + AccountCapsule account = dbManager.getAccountStore().get(ownerAddress); + if (account == null) { throw new ContractValidateException("Account has not existed"); } + if (account.getAccountName() != null && !account.getAccountName().isEmpty()) { + throw new ContractValidateException("This account name already exist"); + } + if (dbManager.getAccountIndexStore().has(accountName)) { + throw new ContractValidateException("This name has existed"); + } } catch (Exception ex) { ex.printStackTrace(); throw new ContractValidateException(ex.getMessage()); diff --git a/src/main/java/org/tron/core/db/Manager.java b/src/main/java/org/tron/core/db/Manager.java index fad5459bcb9..33e213af99d 100644 --- a/src/main/java/org/tron/core/db/Manager.java +++ b/src/main/java/org/tron/core/db/Manager.java @@ -326,6 +326,7 @@ public void initAccount() { account.getAccountType(), account.getBalance()); this.accountStore.put(account.getAddress(), accountCapsule); + this.accountIndexStore.put(accountCapsule); }); } diff --git a/src/test/java/org/tron/core/actuator/UpdateAccountActuatorTest.java b/src/test/java/org/tron/core/actuator/UpdateAccountActuatorTest.java index 7cb8d7967fe..e25b8a0b0bc 100755 --- a/src/test/java/org/tron/core/actuator/UpdateAccountActuatorTest.java +++ b/src/test/java/org/tron/core/actuator/UpdateAccountActuatorTest.java @@ -33,11 +33,12 @@ public class UpdateAccountActuatorTest { private static Any contract; private static final String dbPath = "output_CreateAccountTest"; - private static final String OWNER_ADDRESS_NOT_EXIT = - Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049abc"; private static final String ACCOUNT_NAME = "ownerTest"; + private static final String ACCOUNT_NAME_1 = "ownerTest1"; private static final String OWNER_ADDRESS = Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d4271a1abc"; + private static final String OWNER_ADDRESS_1 = + Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049abc"; private static final String OWNER_ADDRESS_INVALIATE = "aaaa"; static { @@ -61,10 +62,12 @@ public void createCapsule() { AccountCapsule ownerCapsule = new AccountCapsule( ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS)), - ByteString.copyFromUtf8(ACCOUNT_NAME), + ByteString.EMPTY, AccountType.Normal); dbManager.getAccountStore().put(ownerCapsule.getAddress().toByteArray(), ownerCapsule); - dbManager.getAccountStore().delete(ByteArray.fromHexString(OWNER_ADDRESS_NOT_EXIT)); + dbManager.getAccountStore().delete(ByteArray.fromHexString(OWNER_ADDRESS_1)); + dbManager.getAccountIndexStore().delete(ACCOUNT_NAME.getBytes()); + dbManager.getAccountIndexStore().delete(ACCOUNT_NAME_1.getBytes()); } private Any getContract(String name, String address) { @@ -101,6 +104,7 @@ public void rightUpdateAccount() { AccountCapsule accountCapsule = dbManager.getAccountStore() .get(ByteArray.fromHexString(OWNER_ADDRESS)); Assert.assertEquals(ACCOUNT_NAME, accountCapsule.getAccountName().toStringUtf8()); + Assert.assertTrue(true); } catch (ContractValidateException e) { Assert.assertFalse(e instanceof ContractValidateException); } catch (ContractExeException e) { @@ -116,6 +120,7 @@ public void invalidAddress() { try { actuator.validate(); actuator.execute(ret); + Assert.assertFalse(true); } catch (ContractValidateException e) { Assert.assertTrue(e instanceof ContractValidateException); Assert.assertEquals("Invalidate ownerAddress", e.getMessage()); @@ -124,6 +129,105 @@ public void invalidAddress() { } } + @Test + public void noExitAccount() { + TransactionResultCapsule ret = new TransactionResultCapsule(); + UpdateAccountActuator actuator = new UpdateAccountActuator( + getContract(ACCOUNT_NAME, OWNER_ADDRESS_1), dbManager); + try { + actuator.validate(); + actuator.execute(ret); + Assert.assertFalse(true); + } catch (ContractValidateException e) { + Assert.assertTrue(e instanceof ContractValidateException); + Assert.assertEquals("Account has not existed", e.getMessage()); + } catch (ContractExeException e) { + Assert.assertFalse(e instanceof ContractExeException); + } + } + + @Test + /* + * Can update name only one time. + */ + public void twiceUpdateAccount() { + TransactionResultCapsule ret = new TransactionResultCapsule(); + UpdateAccountActuator actuator = new UpdateAccountActuator( + getContract(ACCOUNT_NAME, OWNER_ADDRESS), dbManager); + UpdateAccountActuator actuator1 = new UpdateAccountActuator( + getContract(ACCOUNT_NAME_1, OWNER_ADDRESS), dbManager); + try { + actuator.validate(); + actuator.execute(ret); + Assert.assertEquals(ret.getInstance().getRet(), code.SUCESS); + AccountCapsule accountCapsule = dbManager.getAccountStore() + .get(ByteArray.fromHexString(OWNER_ADDRESS)); + Assert.assertEquals(ACCOUNT_NAME, accountCapsule.getAccountName().toStringUtf8()); + Assert.assertTrue(true); + } catch (ContractValidateException e) { + Assert.assertFalse(e instanceof ContractValidateException); + } catch (ContractExeException e) { + Assert.assertFalse(e instanceof ContractExeException); + } + + try { + actuator1.validate(); + actuator1.execute(ret); + Assert.assertFalse(true); + } catch (ContractValidateException e) { + Assert.assertTrue(e instanceof ContractValidateException); + Assert.assertEquals("This account name already exist", e.getMessage()); + AccountCapsule accountCapsule = dbManager.getAccountStore() + .get(ByteArray.fromHexString(OWNER_ADDRESS)); + Assert.assertEquals(ACCOUNT_NAME, accountCapsule.getAccountName().toStringUtf8()); + } catch (ContractExeException e) { + Assert.assertFalse(e instanceof ContractExeException); + } + } + + @Test + public void nameAlreadyUsed() { + TransactionResultCapsule ret = new TransactionResultCapsule(); + UpdateAccountActuator actuator = new UpdateAccountActuator( + getContract(ACCOUNT_NAME, OWNER_ADDRESS), dbManager); + UpdateAccountActuator actuator1 = new UpdateAccountActuator( + getContract(ACCOUNT_NAME, OWNER_ADDRESS_1), dbManager); + try { + actuator.validate(); + actuator.execute(ret); + Assert.assertEquals(ret.getInstance().getRet(), code.SUCESS); + AccountCapsule accountCapsule = dbManager.getAccountStore() + .get(ByteArray.fromHexString(OWNER_ADDRESS)); + Assert.assertEquals(ACCOUNT_NAME, accountCapsule.getAccountName().toStringUtf8()); + Assert.assertTrue(true); + } catch (ContractValidateException e) { + Assert.assertFalse(e instanceof ContractValidateException); + } catch (ContractExeException e) { + Assert.assertFalse(e instanceof ContractExeException); + } + + AccountCapsule ownerCapsule = + new AccountCapsule( + ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS_1)), + ByteString.EMPTY, + AccountType.Normal); + dbManager.getAccountStore().put(ownerCapsule.getAddress().toByteArray(), ownerCapsule); + + try { + actuator1.validate(); + actuator1.execute(ret); + Assert.assertFalse(true); + } catch (ContractValidateException e) { + Assert.assertTrue(e instanceof ContractValidateException); + Assert.assertEquals("This name has existed", e.getMessage()); + AccountCapsule accountCapsule = dbManager.getAccountStore() + .get(ByteArray.fromHexString(OWNER_ADDRESS)); + Assert.assertEquals(ACCOUNT_NAME, accountCapsule.getAccountName().toStringUtf8()); + } catch (ContractExeException e) { + Assert.assertFalse(e instanceof ContractExeException); + } + } + @Test public void invalidName() { TransactionResultCapsule ret = new TransactionResultCapsule(); @@ -136,7 +240,9 @@ public void invalidName() { Assert.assertEquals(ret.getInstance().getRet(), code.SUCESS); AccountCapsule accountCapsule = dbManager.getAccountStore() .get(ByteArray.fromHexString(OWNER_ADDRESS)); - Assert.assertEquals("testname0123456789abcdefghijgklm", accountCapsule.getAccountName().toStringUtf8()); + Assert.assertEquals("testname0123456789abcdefghijgklm", + accountCapsule.getAccountName().toStringUtf8()); + Assert.assertTrue(true); } catch (ContractValidateException e) { Assert.assertFalse(e instanceof ContractValidateException); } catch (ContractExeException e) { @@ -149,6 +255,7 @@ public void invalidName() { getContract(ByteString.EMPTY, OWNER_ADDRESS), dbManager); actuator.validate(); actuator.execute(ret); + Assert.assertFalse(true); } catch (ContractValidateException e) { Assert.assertTrue(e instanceof ContractValidateException); Assert.assertEquals("Invalidate accountName", e.getMessage()); @@ -162,6 +269,7 @@ public void invalidName() { getContract("testname0123456789abcdefghijgklmo", OWNER_ADDRESS), dbManager); actuator.validate(); actuator.execute(ret); + Assert.assertFalse(true); } catch (ContractValidateException e) { Assert.assertTrue(e instanceof ContractValidateException); Assert.assertEquals("Invalidate accountName", e.getMessage()); @@ -175,6 +283,7 @@ public void invalidName() { getContract("t e", OWNER_ADDRESS), dbManager); actuator.validate(); actuator.execute(ret); + Assert.assertFalse(true); } catch (ContractValidateException e) { Assert.assertTrue(e instanceof ContractValidateException); Assert.assertEquals("Invalidate accountName", e.getMessage()); @@ -188,6 +297,7 @@ public void invalidName() { getContract("测试", OWNER_ADDRESS), dbManager); actuator.validate(); actuator.execute(ret); + Assert.assertFalse(true); } catch (ContractValidateException e) { Assert.assertTrue(e instanceof ContractValidateException); Assert.assertEquals("Invalidate accountName", e.getMessage()); From bff5af2d8beb18bf4e3c951354cb612e7600d151 Mon Sep 17 00:00:00 2001 From: zergweak Date: Wed, 9 May 2018 17:30:55 +0800 Subject: [PATCH 14/17] rm getName of AccountCapsule --- src/main/java/org/tron/core/capsule/AccountCapsule.java | 4 ---- src/main/java/org/tron/core/db/AccountIndexStore.java | 2 +- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/src/main/java/org/tron/core/capsule/AccountCapsule.java b/src/main/java/org/tron/core/capsule/AccountCapsule.java index bf574cbcf72..86756216d08 100644 --- a/src/main/java/org/tron/core/capsule/AccountCapsule.java +++ b/src/main/java/org/tron/core/capsule/AccountCapsule.java @@ -367,8 +367,4 @@ public void setLatestWithdrawTime(long latestWithdrawTime) { .setLatestWithdrawTime(latestWithdrawTime) .build(); } - - public ByteString getName() { - return this.account.getAccountName(); - } } diff --git a/src/main/java/org/tron/core/db/AccountIndexStore.java b/src/main/java/org/tron/core/db/AccountIndexStore.java index 4ac24e60756..011ee051eb5 100644 --- a/src/main/java/org/tron/core/db/AccountIndexStore.java +++ b/src/main/java/org/tron/core/db/AccountIndexStore.java @@ -42,7 +42,7 @@ public static AccountIndexStore create(String dbName) { } public void put(AccountCapsule accountCapsule) { - put(accountCapsule.getName().toByteArray(), + put(accountCapsule.getAccountName().toByteArray(), new BytesCapsule(accountCapsule.getAddress().toByteArray())); } From abf4e38b5df0e9b6ee81cc1b215670dbafeafda4 Mon Sep 17 00:00:00 2001 From: zergweak Date: Wed, 9 May 2018 18:26:24 +0800 Subject: [PATCH 15/17] Adjust the non-null judgment of byte array. --- src/main/java/org/tron/core/Wallet.java | 3 ++- src/main/java/org/tron/core/capsule/utils/TransactionUtil.java | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/tron/core/Wallet.java b/src/main/java/org/tron/core/Wallet.java index 149ed88801b..be38e5cfcdc 100755 --- a/src/main/java/org/tron/core/Wallet.java +++ b/src/main/java/org/tron/core/Wallet.java @@ -38,6 +38,7 @@ import org.tron.common.overlay.message.Message; import org.tron.common.utils.Base58; import org.tron.common.utils.ByteArray; +import org.tron.common.utils.ByteUtil; import org.tron.common.utils.Utils; import org.tron.core.capsule.AccountCapsule; import org.tron.core.capsule.AssetIssueCapsule; @@ -111,7 +112,7 @@ public static void setAddressPreFixByte(byte addressPreFixByte) { } public static boolean addressValid(byte[] address) { - if (address == null || address.length == 0) { + if (ByteUtil.isNullOrZeroArray(address)) { logger.warn("Warning: Address is empty !!"); return false; } diff --git a/src/main/java/org/tron/core/capsule/utils/TransactionUtil.java b/src/main/java/org/tron/core/capsule/utils/TransactionUtil.java index be2e2b49715..68ecec6aa8f 100644 --- a/src/main/java/org/tron/core/capsule/utils/TransactionUtil.java +++ b/src/main/java/org/tron/core/capsule/utils/TransactionUtil.java @@ -17,6 +17,7 @@ import com.google.protobuf.ByteString; import lombok.extern.slf4j.Slf4j; +import org.tron.common.utils.ByteUtil; import org.tron.core.Wallet; import org.tron.core.capsule.TransactionCapsule; import org.tron.protos.Contract.TransferContract; @@ -50,7 +51,7 @@ private static boolean checkBalance(long totalBalance, long totalSpent) { } public static boolean validAccountName(byte[] accountName) { - if (accountName == null || accountName.length == 0) { + if (ByteUtil.isNullOrZeroArray(accountName)) { return false; } if (accountName.length > 32) { From 4666dcb29fc12e0461f709a7a81f1eca1d2d3727 Mon Sep 17 00:00:00 2001 From: zergweak Date: Wed, 9 May 2018 18:28:06 +0800 Subject: [PATCH 16/17] modify UpdateAccountActuator for exception catch and throw --- .../core/actuator/UpdateAccountActuator.java | 85 ++++++++----------- .../actuator/UpdateAccountActuatorTest.java | 29 ------- 2 files changed, 37 insertions(+), 77 deletions(-) diff --git a/src/main/java/org/tron/core/actuator/UpdateAccountActuator.java b/src/main/java/org/tron/core/actuator/UpdateAccountActuator.java index 761a03c69ed..c1613c08455 100644 --- a/src/main/java/org/tron/core/actuator/UpdateAccountActuator.java +++ b/src/main/java/org/tron/core/actuator/UpdateAccountActuator.java @@ -11,7 +11,6 @@ import org.tron.core.db.AccountIndexStore; import org.tron.core.db.AccountStore; import org.tron.core.db.Manager; -import org.tron.core.exception.ContractExeException; import org.tron.core.exception.ContractValidateException; import org.tron.protos.Contract.AccountUpdateContract; import org.tron.protos.Protocol.Transaction.Result.code; @@ -28,69 +27,59 @@ public class UpdateAccountActuator extends AbstractActuator { super(contract, dbManager); try { accountUpdateContract = contract.unpack(AccountUpdateContract.class); - accountName = accountUpdateContract.getAccountName().toByteArray(); - ownerAddress = accountUpdateContract.getOwnerAddress().toByteArray(); - fee = calcFee(); } catch (InvalidProtocolBufferException e) { logger.error(e.getMessage(), e); - } catch (Exception e) { - logger.error(e.getMessage(), e); } + accountName = accountUpdateContract.getAccountName().toByteArray(); + ownerAddress = accountUpdateContract.getOwnerAddress().toByteArray(); + fee = calcFee(); } @Override - public boolean execute(TransactionResultCapsule ret) throws ContractExeException { - try { - AccountStore accountStore = dbManager.getAccountStore(); - AccountIndexStore accountIndexStore = dbManager.getAccountIndexStore(); - AccountCapsule account = accountStore.get(ownerAddress); + public boolean execute(TransactionResultCapsule ret) { + AccountStore accountStore = dbManager.getAccountStore(); + AccountIndexStore accountIndexStore = dbManager.getAccountIndexStore(); + AccountCapsule account = accountStore.get(ownerAddress); - account.setAccountName(accountName); - accountStore.put(ownerAddress, account); - accountIndexStore.put(account); + account.setAccountName(accountName); + accountStore.put(ownerAddress, account); + accountIndexStore.put(account); + + ret.setStatus(fee, code.SUCESS); - ret.setStatus(fee, code.SUCESS); - } catch (Exception e) { - logger.debug(e.getMessage(), e); - ret.setStatus(fee, code.FAILED); - throw new ContractExeException(e.getMessage()); - } return true; } @Override public boolean validate() throws ContractValidateException { - try { - if (this.dbManager == null) { - throw new ContractValidateException("No dbManager!"); - } - if (accountUpdateContract == null) { - throw new ContractValidateException( - "contract type error,expected type [AccountUpdateContract],real type[" + contract - .getClass() + "]"); - } - if (!TransactionUtil.validAccountName(accountName)) { - throw new ContractValidateException("Invalidate accountName"); - } - if (!Wallet.addressValid(ownerAddress)) { - throw new ContractValidateException("Invalidate ownerAddress"); - } + if (this.dbManager == null) { + throw new ContractValidateException("No dbManager!"); + } + if (accountUpdateContract == null) { + throw new ContractValidateException( + "contract type error,expected type [AccountUpdateContract],real type[" + contract + .getClass() + "]"); + } - AccountCapsule account = dbManager.getAccountStore().get(ownerAddress); - if (account == null) { - throw new ContractValidateException("Account has not existed"); - } - if (account.getAccountName() != null && !account.getAccountName().isEmpty()) { - throw new ContractValidateException("This account name already exist"); - } - if (dbManager.getAccountIndexStore().has(accountName)) { - throw new ContractValidateException("This name has existed"); - } - } catch (Exception ex) { - ex.printStackTrace(); - throw new ContractValidateException(ex.getMessage()); + if (!TransactionUtil.validAccountName(accountName)) { + throw new ContractValidateException("Invalidate accountName"); } + if (!Wallet.addressValid(ownerAddress)) { + throw new ContractValidateException("Invalidate ownerAddress"); + } + + AccountCapsule account = dbManager.getAccountStore().get(ownerAddress); + if (account == null) { + throw new ContractValidateException("Account has not existed"); + } + if (account.getAccountName() != null && !account.getAccountName().isEmpty()) { + throw new ContractValidateException("This account name already exist"); + } + if (dbManager.getAccountIndexStore().has(accountName)) { + throw new ContractValidateException("This name has existed"); + } + return true; } diff --git a/src/test/java/org/tron/core/actuator/UpdateAccountActuatorTest.java b/src/test/java/org/tron/core/actuator/UpdateAccountActuatorTest.java index e25b8a0b0bc..52854e44b7a 100755 --- a/src/test/java/org/tron/core/actuator/UpdateAccountActuatorTest.java +++ b/src/test/java/org/tron/core/actuator/UpdateAccountActuatorTest.java @@ -19,7 +19,6 @@ import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; import org.tron.core.db.Manager; -import org.tron.core.exception.ContractExeException; import org.tron.core.exception.ContractValidateException; import org.tron.protos.Contract; import org.tron.protos.Protocol.AccountType; @@ -107,8 +106,6 @@ public void rightUpdateAccount() { Assert.assertTrue(true); } catch (ContractValidateException e) { Assert.assertFalse(e instanceof ContractValidateException); - } catch (ContractExeException e) { - Assert.assertFalse(e instanceof ContractExeException); } } @@ -124,8 +121,6 @@ public void invalidAddress() { } catch (ContractValidateException e) { Assert.assertTrue(e instanceof ContractValidateException); Assert.assertEquals("Invalidate ownerAddress", e.getMessage()); - } catch (ContractExeException e) { - Assert.assertFalse(e instanceof ContractExeException); } } @@ -141,8 +136,6 @@ public void noExitAccount() { } catch (ContractValidateException e) { Assert.assertTrue(e instanceof ContractValidateException); Assert.assertEquals("Account has not existed", e.getMessage()); - } catch (ContractExeException e) { - Assert.assertFalse(e instanceof ContractExeException); } } @@ -166,8 +159,6 @@ public void twiceUpdateAccount() { Assert.assertTrue(true); } catch (ContractValidateException e) { Assert.assertFalse(e instanceof ContractValidateException); - } catch (ContractExeException e) { - Assert.assertFalse(e instanceof ContractExeException); } try { @@ -180,8 +171,6 @@ public void twiceUpdateAccount() { AccountCapsule accountCapsule = dbManager.getAccountStore() .get(ByteArray.fromHexString(OWNER_ADDRESS)); Assert.assertEquals(ACCOUNT_NAME, accountCapsule.getAccountName().toStringUtf8()); - } catch (ContractExeException e) { - Assert.assertFalse(e instanceof ContractExeException); } } @@ -202,8 +191,6 @@ public void nameAlreadyUsed() { Assert.assertTrue(true); } catch (ContractValidateException e) { Assert.assertFalse(e instanceof ContractValidateException); - } catch (ContractExeException e) { - Assert.assertFalse(e instanceof ContractExeException); } AccountCapsule ownerCapsule = @@ -223,8 +210,6 @@ public void nameAlreadyUsed() { AccountCapsule accountCapsule = dbManager.getAccountStore() .get(ByteArray.fromHexString(OWNER_ADDRESS)); Assert.assertEquals(ACCOUNT_NAME, accountCapsule.getAccountName().toStringUtf8()); - } catch (ContractExeException e) { - Assert.assertFalse(e instanceof ContractExeException); } } @@ -245,10 +230,7 @@ public void invalidName() { Assert.assertTrue(true); } catch (ContractValidateException e) { Assert.assertFalse(e instanceof ContractValidateException); - } catch (ContractExeException e) { - Assert.assertFalse(e instanceof ContractExeException); } - //Empty name try { UpdateAccountActuator actuator = new UpdateAccountActuator( @@ -259,10 +241,7 @@ public void invalidName() { } catch (ContractValidateException e) { Assert.assertTrue(e instanceof ContractValidateException); Assert.assertEquals("Invalidate accountName", e.getMessage()); - } catch (ContractExeException e) { - Assert.assertFalse(e instanceof ContractExeException); } - //Too long name try { UpdateAccountActuator actuator = new UpdateAccountActuator( @@ -273,10 +252,7 @@ public void invalidName() { } catch (ContractValidateException e) { Assert.assertTrue(e instanceof ContractValidateException); Assert.assertEquals("Invalidate accountName", e.getMessage()); - } catch (ContractExeException e) { - Assert.assertFalse(e instanceof ContractExeException); } - //Can't contain space try { UpdateAccountActuator actuator = new UpdateAccountActuator( @@ -287,10 +263,7 @@ public void invalidName() { } catch (ContractValidateException e) { Assert.assertTrue(e instanceof ContractValidateException); Assert.assertEquals("Invalidate accountName", e.getMessage()); - } catch (ContractExeException e) { - Assert.assertFalse(e instanceof ContractExeException); } - //Can't contain chinese characters try { UpdateAccountActuator actuator = new UpdateAccountActuator( @@ -301,8 +274,6 @@ public void invalidName() { } catch (ContractValidateException e) { Assert.assertTrue(e instanceof ContractValidateException); Assert.assertEquals("Invalidate accountName", e.getMessage()); - } catch (ContractExeException e) { - Assert.assertFalse(e instanceof ContractExeException); } } From 4f44d81116a941d1c40a9fcd3acdc8d2800b0a15 Mon Sep 17 00:00:00 2001 From: zergweak Date: Wed, 9 May 2018 20:13:01 +0800 Subject: [PATCH 17/17] rm space --- .../java/org/tron/core/actuator/UpdateAccountActuator.java | 1 - src/main/java/org/tron/core/capsule/AccountCapsule.java | 1 - src/main/java/org/tron/core/db/AccountIndexStore.java | 3 --- src/test/java/org/tron/core/db/AccountIndexStoreTest.java | 2 -- 4 files changed, 7 deletions(-) diff --git a/src/main/java/org/tron/core/actuator/UpdateAccountActuator.java b/src/main/java/org/tron/core/actuator/UpdateAccountActuator.java index c1613c08455..4b560fdb1d7 100644 --- a/src/main/java/org/tron/core/actuator/UpdateAccountActuator.java +++ b/src/main/java/org/tron/core/actuator/UpdateAccountActuator.java @@ -52,7 +52,6 @@ public boolean execute(TransactionResultCapsule ret) { @Override public boolean validate() throws ContractValidateException { - if (this.dbManager == null) { throw new ContractValidateException("No dbManager!"); } diff --git a/src/main/java/org/tron/core/capsule/AccountCapsule.java b/src/main/java/org/tron/core/capsule/AccountCapsule.java index 86756216d08..8463540633b 100644 --- a/src/main/java/org/tron/core/capsule/AccountCapsule.java +++ b/src/main/java/org/tron/core/capsule/AccountCapsule.java @@ -169,7 +169,6 @@ public ByteString getAccountName() { return this.account.getAccountName(); } - public long getBalance() { return this.account.getBalance(); } diff --git a/src/main/java/org/tron/core/db/AccountIndexStore.java b/src/main/java/org/tron/core/db/AccountIndexStore.java index 011ee051eb5..baf2029dc04 100644 --- a/src/main/java/org/tron/core/db/AccountIndexStore.java +++ b/src/main/java/org/tron/core/db/AccountIndexStore.java @@ -12,11 +12,9 @@ @Component public class AccountIndexStore extends TronStoreWithRevoking { - @Autowired public AccountIndexStore(@Qualifier("account-index") String dbName) { super(dbName); - } private static AccountIndexStore instance; @@ -63,7 +61,6 @@ public BytesCapsule get(byte[] key) { return new BytesCapsule(value); } - @Override public boolean has(byte[] key) { byte[] value = dbSource.getData(key); diff --git a/src/test/java/org/tron/core/db/AccountIndexStoreTest.java b/src/test/java/org/tron/core/db/AccountIndexStoreTest.java index 0804df93299..d6aa60e954b 100644 --- a/src/test/java/org/tron/core/db/AccountIndexStoreTest.java +++ b/src/test/java/org/tron/core/db/AccountIndexStoreTest.java @@ -40,7 +40,6 @@ public class AccountIndexStoreTest { context = new AnnotationConfigApplicationContext(DefaultConfig.class); } - @AfterClass public static void destroy() { Args.clearParam(); @@ -65,7 +64,6 @@ public static void init() { accountIndexStore.put(accountCapsule4); } - @Test public void putAndGet() { byte[] address = accountIndexStore.get(ByteString.copyFrom(ACCOUNT_NAME_ONE));