| @@ -1,6 +1,7 @@ | |||
| package com.jd.blockchain.ledger.core; | |||
| import com.jd.blockchain.crypto.HashDigest; | |||
| import com.jd.blockchain.ledger.Account; | |||
| import com.jd.blockchain.ledger.BlockchainIdentity; | |||
| import com.jd.blockchain.ledger.HashProof; | |||
| import com.jd.blockchain.ledger.MerkleSnapshot; | |||
| @@ -8,11 +9,11 @@ import com.jd.blockchain.ledger.TypedValue; | |||
| import com.jd.blockchain.utils.Bytes; | |||
| import com.jd.blockchain.utils.Dataset; | |||
| public class AccountDecorator implements LedgerAccount, HashProvable, MerkleSnapshot{ | |||
| public class AccountDecorator implements Account, HashProvable, MerkleSnapshot{ | |||
| private MerkleAccount mklAccount; | |||
| private CompositeAccount mklAccount; | |||
| public AccountDecorator(MerkleAccount mklAccount) { | |||
| public AccountDecorator(CompositeAccount mklAccount) { | |||
| this.mklAccount = mklAccount; | |||
| } | |||
| @@ -0,0 +1,12 @@ | |||
| package com.jd.blockchain.ledger.core; | |||
| import com.jd.blockchain.ledger.Account; | |||
| import com.jd.blockchain.ledger.MerkleSnapshot; | |||
| import com.jd.blockchain.ledger.TypedValue; | |||
| import com.jd.blockchain.utils.Dataset; | |||
| public interface CompositeAccount extends Account, MerkleSnapshot, HashProvable{ | |||
| Dataset<String, TypedValue> getHeaders(); | |||
| } | |||
| @@ -12,7 +12,7 @@ public class ContractAccount extends AccountDecorator implements ContractInfo { | |||
| private static final String CHAIN_CODE_KEY = "CHAIN-CODE"; | |||
| public ContractAccount(MerkleAccount mklAccount) { | |||
| public ContractAccount(CompositeAccount mklAccount) { | |||
| super(mklAccount); | |||
| } | |||
| @@ -67,7 +67,7 @@ public class ContractAccountSet implements Transactional, ContractAccountQuery { | |||
| @Override | |||
| public ContractAccount getAccount(Bytes address) { | |||
| MerkleAccount accBase = accountSet.getAccount(address); | |||
| CompositeAccount accBase = accountSet.getAccount(address); | |||
| return new ContractAccount(accBase); | |||
| } | |||
| @@ -78,7 +78,7 @@ public class ContractAccountSet implements Transactional, ContractAccountQuery { | |||
| @Override | |||
| public ContractAccount getAccount(Bytes address, long version) { | |||
| MerkleAccount accBase = accountSet.getAccount(address, version); | |||
| CompositeAccount accBase = accountSet.getAccount(address, version); | |||
| return new ContractAccount(accBase); | |||
| } | |||
| @@ -93,7 +93,7 @@ public class ContractAccountSet implements Transactional, ContractAccountQuery { | |||
| */ | |||
| public ContractAccount deploy(Bytes address, PubKey pubKey, DigitalSignature addressSignature, byte[] chaincode) { | |||
| // TODO: 校验和记录合约地址签名; | |||
| MerkleAccount accBase = accountSet.register(address, pubKey); | |||
| CompositeAccount accBase = accountSet.register(address, pubKey); | |||
| ContractAccount contractAcc = new ContractAccount(accBase); | |||
| contractAcc.setChaincode(chaincode, -1); | |||
| return contractAcc; | |||
| @@ -108,7 +108,7 @@ public class ContractAccountSet implements Transactional, ContractAccountQuery { | |||
| * @return 返回链码的新版本号; | |||
| */ | |||
| public long update(Bytes address, byte[] chaincode, long version) { | |||
| MerkleAccount accBase = accountSet.getAccount(address); | |||
| CompositeAccount accBase = accountSet.getAccount(address); | |||
| ContractAccount contractAcc = new ContractAccount(accBase); | |||
| return contractAcc.setChaincode(chaincode, version); | |||
| } | |||
| @@ -1,16 +1,8 @@ | |||
| package com.jd.blockchain.ledger.core; | |||
| import com.jd.blockchain.binaryproto.BinaryProtocol; | |||
| import com.jd.blockchain.ledger.BytesValue; | |||
| import com.jd.blockchain.ledger.TypedKVEntry; | |||
| import com.jd.blockchain.ledger.TypedKVData; | |||
| import com.jd.blockchain.ledger.MerkleProof; | |||
| import com.jd.blockchain.ledger.TypedValue; | |||
| import com.jd.blockchain.utils.Bytes; | |||
| public class DataAccount extends AccountDecorator { | |||
| public DataAccount(MerkleAccount mklAccount) { | |||
| public DataAccount(CompositeAccount mklAccount) { | |||
| super(mklAccount); | |||
| } | |||
| @@ -65,7 +65,7 @@ public class DataAccountSet implements Transactional, DataAccountQuery { | |||
| public DataAccount register(Bytes address, PubKey pubKey, DigitalSignature addressSignature) { | |||
| // TODO: 未实现对地址签名的校验和记录; | |||
| MerkleAccount accBase = accountSet.register(address, pubKey); | |||
| CompositeAccount accBase = accountSet.register(address, pubKey); | |||
| return new DataAccount(accBase); | |||
| } | |||
| @@ -83,7 +83,7 @@ public class DataAccountSet implements Transactional, DataAccountQuery { | |||
| */ | |||
| @Override | |||
| public DataAccount getAccount(Bytes address) { | |||
| MerkleAccount accBase = accountSet.getAccount(address); | |||
| CompositeAccount accBase = accountSet.getAccount(address); | |||
| if (accBase == null) { | |||
| return null; | |||
| } | |||
| @@ -92,7 +92,7 @@ public class DataAccountSet implements Transactional, DataAccountQuery { | |||
| @Override | |||
| public DataAccount getAccount(Bytes address, long version) { | |||
| MerkleAccount accBase = accountSet.getAccount(address, version); | |||
| CompositeAccount accBase = accountSet.getAccount(address, version); | |||
| return new DataAccount(accBase); | |||
| } | |||
| @@ -1,13 +0,0 @@ | |||
| package com.jd.blockchain.ledger.core; | |||
| import com.jd.blockchain.ledger.BlockchainIdentity; | |||
| import com.jd.blockchain.ledger.TypedValue; | |||
| import com.jd.blockchain.utils.Dataset; | |||
| public interface LedgerAccount { | |||
| BlockchainIdentity getID(); | |||
| Dataset<String, TypedValue> getDataset(); | |||
| } | |||
| @@ -26,7 +26,7 @@ import com.jd.blockchain.utils.Transactional; | |||
| * @author huanghaiquan | |||
| * | |||
| */ | |||
| public class MerkleAccount implements LedgerAccount, HashProvable, MerkleSnapshot, Transactional { | |||
| public class MerkleAccount implements CompositeAccount, HashProvable, MerkleSnapshot, Transactional { | |||
| private static final Bytes HEADER_PREFIX = Bytes.fromString("HD/"); | |||
| private static final Bytes DATA_PREFIX = Bytes.fromString("DT/"); | |||
| @@ -179,7 +179,7 @@ public class MerkleAccount implements LedgerAccount, HashProvable, MerkleSnapsho | |||
| return accountID; | |||
| } | |||
| protected Dataset<String, TypedValue> getHeaders() { | |||
| public Dataset<String, TypedValue> getHeaders() { | |||
| return typedHeader; | |||
| } | |||
| @@ -20,7 +20,7 @@ import com.jd.blockchain.utils.Bytes; | |||
| import com.jd.blockchain.utils.DataEntry; | |||
| import com.jd.blockchain.utils.Transactional; | |||
| public class MerkleAccountSet implements Transactional, MerkleProvable, AccountQuery<MerkleAccount> { | |||
| public class MerkleAccountSet implements Transactional, MerkleProvable, AccountQuery<CompositeAccount> { | |||
| static { | |||
| DataContractRegistry.register(MerkleSnapshot.class); | |||
| @@ -111,7 +111,7 @@ public class MerkleAccountSet implements Transactional, MerkleProvable, AccountQ | |||
| } | |||
| @Override | |||
| public MerkleAccount getAccount(String address) { | |||
| public CompositeAccount getAccount(String address) { | |||
| return getAccount(Bytes.fromBase58(address)); | |||
| } | |||
| @@ -122,7 +122,7 @@ public class MerkleAccountSet implements Transactional, MerkleProvable, AccountQ | |||
| * @return | |||
| */ | |||
| @Override | |||
| public MerkleAccount getAccount(Bytes address) { | |||
| public CompositeAccount getAccount(Bytes address) { | |||
| return this.getAccount(address, -1); | |||
| } | |||
| @@ -174,7 +174,7 @@ public class MerkleAccountSet implements Transactional, MerkleProvable, AccountQ | |||
| * @param version 账户版本;如果指定为 -1,则返回最新版本; | |||
| * @return | |||
| */ | |||
| public MerkleAccount getAccount(Bytes address, long version) { | |||
| public CompositeAccount getAccount(Bytes address, long version) { | |||
| version = version < 0 ? -1 : version; | |||
| InnerMerkleAccount acc = latestAccountsCache.get(address); | |||
| if (acc != null && version == -1) { | |||
| @@ -206,9 +206,10 @@ public class MerkleAccountSet implements Transactional, MerkleProvable, AccountQ | |||
| // Now, be sure that "acc == null", so get account from storage; | |||
| // Set readonly for the old version account; | |||
| boolean readonly = (version > -1 && version < latestVersion) || isReadonly(); | |||
| long qVersion = version == -1 ? latestVersion : version; | |||
| // load account from storage; | |||
| acc = loadAccount(address, readonly, version); | |||
| acc = loadAccount(address, readonly, qVersion); | |||
| if (acc == null) { | |||
| return null; | |||
| } | |||
| @@ -220,7 +221,7 @@ public class MerkleAccountSet implements Transactional, MerkleProvable, AccountQ | |||
| return acc; | |||
| } | |||
| public MerkleAccount register(Bytes address, PubKey pubKey) { | |||
| public CompositeAccount register(Bytes address, PubKey pubKey) { | |||
| return register(new BlockchainIdentityData(address, pubKey)); | |||
| } | |||
| @@ -235,7 +236,7 @@ public class MerkleAccountSet implements Transactional, MerkleProvable, AccountQ | |||
| * @param pubKey 公钥; | |||
| * @return 注册成功的账户对象; | |||
| */ | |||
| public MerkleAccount register(BlockchainIdentity accountId) { | |||
| public CompositeAccount register(BlockchainIdentity accountId) { | |||
| if (isReadonly()) { | |||
| throw new IllegalArgumentException("This AccountSet is readonly!"); | |||
| } | |||
| @@ -281,6 +282,14 @@ public class MerkleAccountSet implements Transactional, MerkleProvable, AccountQ | |||
| return new InnerMerkleAccount(header, cryptoSetting, keyPrefix, baseExStorage, baseVerStorage); | |||
| } | |||
| /** | |||
| * 加载指定版本的账户; | |||
| * | |||
| * @param address 账户地址; | |||
| * @param readonly 是否只读; | |||
| * @param version 账户的版本;大于等于 0 ; | |||
| * @return | |||
| */ | |||
| private InnerMerkleAccount loadAccount(Bytes address, boolean readonly, long version) { | |||
| byte[] rootHashBytes = merkleDataset.getValue(address, version); | |||
| if (rootHashBytes == null) { | |||
| @@ -4,13 +4,11 @@ import java.util.Map; | |||
| import com.jd.blockchain.crypto.HashDigest; | |||
| import com.jd.blockchain.ledger.CryptoSetting; | |||
| import com.jd.blockchain.ledger.MerkleProof; | |||
| import com.jd.blockchain.ledger.MerkleSnapshot; | |||
| import com.jd.blockchain.storage.service.ExPolicyKVStorage; | |||
| import com.jd.blockchain.storage.service.VersioningKVStorage; | |||
| import com.jd.blockchain.utils.Bytes; | |||
| import com.jd.blockchain.utils.Transactional; | |||
| import com.jd.blockchain.utils.Dataset; | |||
| public class MerkleDataCluster implements Transactional, MerkleSnapshot { | |||
| @@ -1,12 +1,5 @@ | |||
| package com.jd.blockchain.ledger.core; | |||
| import java.util.Set; | |||
| import com.jd.blockchain.ledger.BlockchainIdentity; | |||
| import com.jd.blockchain.ledger.LedgerPermission; | |||
| import com.jd.blockchain.ledger.LedgerSecurityException; | |||
| import com.jd.blockchain.ledger.TransactionPermission; | |||
| public class SecurityContext { | |||
| private static ThreadLocal<SecurityPolicy> policyHolder = new ThreadLocal<SecurityPolicy>(); | |||
| @@ -19,8 +19,8 @@ public class UserAccount extends AccountDecorator implements UserInfo { // imple | |||
| private static final String DATA_PUB_KEY = "DATA-PUBKEY"; | |||
| public UserAccount(MerkleAccount mklAccount) { | |||
| super(mklAccount); | |||
| public UserAccount(CompositeAccount baseAccount) { | |||
| super(baseAccount); | |||
| } | |||
| private PubKey dataPubKey; | |||
| @@ -72,7 +72,7 @@ public class UserAccountSet implements Transactional, UserAccountQuery { | |||
| @Override | |||
| public UserAccount getAccount(Bytes address) { | |||
| MerkleAccount baseAccount = accountSet.getAccount(address); | |||
| CompositeAccount baseAccount = accountSet.getAccount(address); | |||
| return new UserAccount(baseAccount); | |||
| } | |||
| @@ -83,7 +83,7 @@ public class UserAccountSet implements Transactional, UserAccountQuery { | |||
| @Override | |||
| public UserAccount getAccount(Bytes address, long version) { | |||
| MerkleAccount baseAccount = accountSet.getAccount(address, version); | |||
| CompositeAccount baseAccount = accountSet.getAccount(address, version); | |||
| return new UserAccount(baseAccount); | |||
| } | |||
| @@ -99,7 +99,7 @@ public class UserAccountSet implements Transactional, UserAccountQuery { | |||
| * @return 注册成功的用户对象; | |||
| */ | |||
| public UserAccount register(Bytes address, PubKey pubKey) { | |||
| MerkleAccount baseAccount = accountSet.register(address, pubKey); | |||
| CompositeAccount baseAccount = accountSet.register(address, pubKey); | |||
| return new UserAccount(baseAccount); | |||
| } | |||
| @@ -14,8 +14,8 @@ import com.jd.blockchain.crypto.service.classic.ClassicCryptoService; | |||
| import com.jd.blockchain.crypto.service.sm.SMCryptoService; | |||
| import com.jd.blockchain.ledger.BlockchainKeyGenerator; | |||
| import com.jd.blockchain.ledger.BlockchainKeypair; | |||
| import com.jd.blockchain.ledger.core.CompositeAccount; | |||
| import com.jd.blockchain.ledger.core.CryptoConfig; | |||
| import com.jd.blockchain.ledger.core.MerkleAccount; | |||
| import com.jd.blockchain.ledger.core.MerkleAccountSet; | |||
| import com.jd.blockchain.ledger.core.OpeningAccessPolicy; | |||
| import com.jd.blockchain.storage.service.utils.MemoryKVStorage; | |||
| @@ -50,7 +50,7 @@ public class AccountSetTest { | |||
| accset.register(userKey.getAddress(), userKey.getPubKey()); | |||
| //尚未提交之前,可以检索到账户的存在,但版本仍然标记为 -1; | |||
| MerkleAccount userAcc = accset.getAccount(userKey.getAddress()); | |||
| CompositeAccount userAcc = accset.getAccount(userKey.getAddress()); | |||
| assertNotNull(userAcc); | |||
| assertTrue(accset.contains(userKey.getAddress())); | |||
| @@ -59,12 +59,12 @@ public class AccountSetTest { | |||
| assertNotNull(rootHash); | |||
| MerkleAccountSet reloadAccSet = new MerkleAccountSet(rootHash, cryptoConf, Bytes.fromString(keyPrefix), storage, storage, true, accessPolicy); | |||
| MerkleAccount reloadUserAcc = reloadAccSet.getAccount(userKey.getAddress()); | |||
| CompositeAccount reloadUserAcc = reloadAccSet.getAccount(userKey.getAddress()); | |||
| assertNotNull(reloadUserAcc); | |||
| assertTrue(reloadAccSet.contains(userKey.getAddress())); | |||
| assertEquals(userAcc.getAddress(), reloadUserAcc.getAddress()); | |||
| assertEquals(userAcc.getPubKey(), reloadUserAcc.getPubKey()); | |||
| assertEquals(userAcc.getID().getAddress(), reloadUserAcc.getID().getAddress()); | |||
| assertEquals(userAcc.getID().getPubKey(), reloadUserAcc.getID().getPubKey()); | |||
| } | |||
| } | |||
| @@ -44,12 +44,18 @@ public class LedgerTestUtils { | |||
| partiKeys[1] = BlockchainKeyGenerator.getInstance().generate(); | |||
| return createLedgerInitSetting(partiKeys); | |||
| } | |||
| public static LedgerInitSetting createLedgerInitSetting(BlockchainKeypair[] partiKeys) { | |||
| public static CryptoProvider[] getContextProviders() { | |||
| CryptoProvider[] supportedProviders = new CryptoProvider[SUPPORTED_PROVIDERS.length]; | |||
| for (int i = 0; i < SUPPORTED_PROVIDERS.length; i++) { | |||
| supportedProviders[i] = Crypto.getProvider(SUPPORTED_PROVIDERS[i]); | |||
| } | |||
| return supportedProviders; | |||
| } | |||
| public static LedgerInitSetting createLedgerInitSetting(BlockchainKeypair[] partiKeys) { | |||
| CryptoProvider[] supportedProviders =getContextProviders(); | |||
| CryptoConfig defCryptoSetting = new CryptoConfig(); | |||
| defCryptoSetting.setSupportedProviders(supportedProviders); | |||
| @@ -0,0 +1,58 @@ | |||
| package test.com.jd.blockchain.ledger.core; | |||
| import static org.junit.Assert.assertEquals; | |||
| import static org.junit.Assert.assertNotNull; | |||
| import org.junit.Test; | |||
| import com.jd.blockchain.crypto.Crypto; | |||
| import com.jd.blockchain.ledger.BlockchainKeyGenerator; | |||
| import com.jd.blockchain.ledger.BlockchainKeypair; | |||
| import com.jd.blockchain.ledger.TypedValue; | |||
| import com.jd.blockchain.ledger.core.CompositeAccount; | |||
| import com.jd.blockchain.ledger.core.CryptoConfig; | |||
| import com.jd.blockchain.ledger.core.MerkleAccountSet; | |||
| import com.jd.blockchain.ledger.core.OpeningAccessPolicy; | |||
| import com.jd.blockchain.storage.service.utils.MemoryKVStorage; | |||
| import com.jd.blockchain.utils.Bytes; | |||
| public class MerkleAccountSetTest { | |||
| @Test | |||
| public void testRegister() { | |||
| final OpeningAccessPolicy POLICY = new OpeningAccessPolicy(); | |||
| final MemoryKVStorage STORAGE = new MemoryKVStorage(); | |||
| Bytes KEY_PREFIX = Bytes.fromString("/ACCOUNT"); | |||
| CryptoConfig cryptoConfig = new CryptoConfig(); | |||
| cryptoConfig.setSupportedProviders(LedgerTestUtils.getContextProviders()); | |||
| cryptoConfig.setAutoVerifyHash(true); | |||
| cryptoConfig.setHashAlgorithm(Crypto.getAlgorithm("SHA256")); | |||
| MerkleAccountSet accountset = new MerkleAccountSet(cryptoConfig, KEY_PREFIX, STORAGE, STORAGE, POLICY); | |||
| BlockchainKeypair key1 = BlockchainKeyGenerator.getInstance().generate(); | |||
| accountset.register(key1.getIdentity()); | |||
| accountset.commit(); | |||
| CompositeAccount acc1 = accountset.getAccount(key1.getAddress()); | |||
| assertNotNull(acc1); | |||
| assertEquals(0, accountset.getVersion(key1.getAddress())); | |||
| acc1.getDataset().setValue("K1", TypedValue.fromText("V0"), -1); | |||
| TypedValue v1 = acc1.getDataset().getValue("K1"); | |||
| assertNotNull(v1); | |||
| assertEquals(0, acc1.getDataset().getVersion("K1")); | |||
| accountset.commit(); | |||
| v1 = acc1.getDataset().getValue("K1"); | |||
| assertNotNull(v1); | |||
| assertEquals(0, acc1.getDataset().getVersion("K1")); | |||
| } | |||
| } | |||
| @@ -340,6 +340,7 @@ public class TransactionBatchProcessorTest { | |||
| 0); | |||
| BytesValue v3 = ledgerRepo.getDataAccountSet().getAccount(dataAccountKeypair.getAddress()).getDataset().getValue("K3", | |||
| 0); | |||
| assertNotNull(v1_0); | |||
| assertNotNull(v1_1); | |||
| @@ -0,0 +1,11 @@ | |||
| package com.jd.blockchain.ledger; | |||
| import com.jd.blockchain.utils.Dataset; | |||
| public interface Account { | |||
| BlockchainIdentity getID(); | |||
| Dataset<String, TypedValue> getDataset(); | |||
| } | |||