|
@@ -285,7 +285,7 @@ public class MerkleTree implements Transactional { |
|
|
if (sn > MAX_SN) { |
|
|
if (sn > MAX_SN) { |
|
|
throw new IllegalArgumentException("The sn is great than MAX[" + MAX_SN + "]!"); |
|
|
throw new IllegalArgumentException("The sn is great than MAX[" + MAX_SN + "]!"); |
|
|
} |
|
|
} |
|
|
DataNode dataNode = DataNode.newDataNode(setting.getHashAlgorithm(), sn, key, version, hashedData); |
|
|
|
|
|
|
|
|
DataNode dataNode = MerkleTreeEncoder.newDataNode(setting.getHashAlgorithm(), sn, key, version, hashedData); |
|
|
updatedDataNodes.put(sn, dataNode); |
|
|
updatedDataNodes.put(sn, dataNode); |
|
|
return dataNode; |
|
|
return dataNode; |
|
|
} |
|
|
} |
|
@@ -844,7 +844,7 @@ public class MerkleTree implements Transactional { |
|
|
if (bytes == null || bytes.length == 0) { |
|
|
if (bytes == null || bytes.length == 0) { |
|
|
return null; |
|
|
return null; |
|
|
} |
|
|
} |
|
|
DataNode dataNode = DataNode.parse(bytes); |
|
|
|
|
|
|
|
|
DataNode dataNode = MerkleTreeEncoder.parse(bytes); |
|
|
if (verify && !hashBytes.equals(dataNode.nodeHash)) { |
|
|
if (verify && !hashBytes.equals(dataNode.nodeHash)) { |
|
|
String keyStr = hashBytes.toBase58(); |
|
|
String keyStr = hashBytes.toBase58(); |
|
|
String actualHashStr = dataNode.nodeHash.toBase58(); |
|
|
String actualHashStr = dataNode.nodeHash.toBase58(); |
|
@@ -1429,7 +1429,7 @@ public class MerkleTree implements Transactional { |
|
|
* @author huanghaiquan |
|
|
* @author huanghaiquan |
|
|
* |
|
|
* |
|
|
*/ |
|
|
*/ |
|
|
private static class DataNode extends AbstractMerkleNode implements MerkleDataNode { |
|
|
|
|
|
|
|
|
static class DataNode extends AbstractMerkleNode implements MerkleDataNode { |
|
|
|
|
|
|
|
|
private long sn; |
|
|
private long sn; |
|
|
|
|
|
|
|
@@ -1439,7 +1439,7 @@ public class MerkleTree implements Transactional { |
|
|
|
|
|
|
|
|
private byte[] dataNodeBytes; |
|
|
private byte[] dataNodeBytes; |
|
|
|
|
|
|
|
|
private DataNode(long sn, Bytes key, long version, HashDigest dataHash, byte[] dataBytes) { |
|
|
|
|
|
|
|
|
DataNode(long sn, Bytes key, long version, HashDigest dataHash, byte[] dataBytes) { |
|
|
this.sn = sn; |
|
|
this.sn = sn; |
|
|
this.key = key; |
|
|
this.key = key; |
|
|
this.version = version; |
|
|
this.version = version; |
|
@@ -1447,55 +1447,6 @@ public class MerkleTree implements Transactional { |
|
|
this.dataNodeBytes = dataBytes; |
|
|
this.dataNodeBytes = dataBytes; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
@SuppressWarnings("unused") |
|
|
|
|
|
private static DataNode newDataNode(CryptoAlgorithm hashAlgorithm, long sn, Bytes key, long version, |
|
|
|
|
|
byte[] hashedData) { |
|
|
|
|
|
return newDataNode(hashAlgorithm.code(), sn, key, version, hashedData); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private static DataNode newDataNode(short hashAlgorithm, long sn, Bytes key, long version, byte[] hashedData) { |
|
|
|
|
|
// byte[] keyStrBytes = BytesUtils.toBytes(key); |
|
|
|
|
|
// int maskSize = NumberMask.SHORT.getMaskLength(keyStrBytes.length); |
|
|
|
|
|
int keySize = key.size(); |
|
|
|
|
|
int maskSize = NumberMask.SHORT.getMaskLength(keySize); |
|
|
|
|
|
|
|
|
|
|
|
// int bodySize = 8 + maskSize + keyStrBytes.length + 8;// sn + key + version; |
|
|
|
|
|
int bodySize = 8 + maskSize + keySize + 8;// sn + key + version; |
|
|
|
|
|
byte[] bodyBytes = new byte[bodySize]; |
|
|
|
|
|
|
|
|
|
|
|
int offset = 0; |
|
|
|
|
|
offset += BytesUtils.toBytes(sn, bodyBytes, 0); |
|
|
|
|
|
|
|
|
|
|
|
// NumberMask.SHORT.writeMask(keyStrBytes.length, bodyBytes, offset); |
|
|
|
|
|
NumberMask.SHORT.writeMask(keySize, bodyBytes, offset); |
|
|
|
|
|
offset += maskSize; |
|
|
|
|
|
|
|
|
|
|
|
// System.arraycopy(keyStrBytes, 0, bodyBytes, offset, keyStrBytes.length); |
|
|
|
|
|
// System.arraycopy(keyStrBytes, 0, bodyBytes, offset, keyStrBytes.length); |
|
|
|
|
|
// offset += keyStrBytes.length; |
|
|
|
|
|
offset += key.copyTo(bodyBytes, offset, keySize); |
|
|
|
|
|
|
|
|
|
|
|
// TODO: version; |
|
|
|
|
|
offset += BytesUtils.toBytes(version, bodyBytes, offset); |
|
|
|
|
|
|
|
|
|
|
|
byte[] dataBytes = BytesUtils.concat(bodyBytes, hashedData); |
|
|
|
|
|
|
|
|
|
|
|
HashFunction hashFunc = Crypto.getHashFunction(hashAlgorithm); |
|
|
|
|
|
HashDigest dataHash = hashFunc.hash(dataBytes); |
|
|
|
|
|
|
|
|
|
|
|
int hashMaskSize = NumberMask.TINY.getMaskLength(dataHash.size()); |
|
|
|
|
|
int dataNodeSize = bodySize + hashMaskSize + dataHash.size(); |
|
|
|
|
|
byte[] dataNodeBytes = new byte[dataNodeSize]; |
|
|
|
|
|
|
|
|
|
|
|
offset = 0; |
|
|
|
|
|
System.arraycopy(bodyBytes, 0, dataNodeBytes, offset, bodySize); |
|
|
|
|
|
offset += bodySize; |
|
|
|
|
|
NumberMask.TINY.writeMask(dataHash.size(), dataNodeBytes, offset); |
|
|
|
|
|
offset += hashMaskSize; |
|
|
|
|
|
System.arraycopy(dataHash.toBytes(), 0, dataNodeBytes, offset, dataHash.size()); |
|
|
|
|
|
|
|
|
|
|
|
return new DataNode(sn, key, version, dataHash, dataNodeBytes); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@Override |
|
|
@Override |
|
|
protected long getStartingSN() { |
|
|
protected long getStartingSN() { |
|
@@ -1577,37 +1528,6 @@ public class MerkleTree implements Transactional { |
|
|
return dataNodeBytes; |
|
|
return dataNodeBytes; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
private static DataNode parse(byte[] bytes) { |
|
|
|
|
|
// InputStream in = new ByteArrayInputStream(bytes); |
|
|
|
|
|
|
|
|
|
|
|
int offset = 0; |
|
|
|
|
|
long sn = BytesUtils.toLong(bytes, offset); |
|
|
|
|
|
offset += 8; |
|
|
|
|
|
|
|
|
|
|
|
// byte[] keyBytes = BytesEncoding.read(NumberMask.SHORT, in); |
|
|
|
|
|
// String key = BytesUtils.toString(keyBytes); |
|
|
|
|
|
int keySize = NumberMask.SHORT.resolveMaskedNumber(bytes, offset); |
|
|
|
|
|
offset += NumberMask.SHORT.getMaskLength(keySize); |
|
|
|
|
|
byte[] keyBytes = new byte[keySize]; |
|
|
|
|
|
System.arraycopy(bytes, offset, keyBytes, 0, keySize); |
|
|
|
|
|
offset += keySize; |
|
|
|
|
|
// String key = BytesUtils.toString(keyBytes); |
|
|
|
|
|
Bytes key = new Bytes(keyBytes); |
|
|
|
|
|
|
|
|
|
|
|
// long version = BytesUtils.readLong(in); |
|
|
|
|
|
long version = BytesUtils.toLong(bytes, offset); |
|
|
|
|
|
offset += 8; |
|
|
|
|
|
|
|
|
|
|
|
// byte[] dataHashBytes = BytesEncoding.read(NumberMask.SHORT, in); |
|
|
|
|
|
int hashSize = NumberMask.TINY.resolveMaskedNumber(bytes, offset); |
|
|
|
|
|
offset += NumberMask.TINY.getMaskLength(hashSize); |
|
|
|
|
|
byte[] dataHashBytes = new byte[hashSize]; |
|
|
|
|
|
System.arraycopy(bytes, offset, dataHashBytes, 0, hashSize); |
|
|
|
|
|
offset += hashSize; |
|
|
|
|
|
HashDigest dataHash = new HashDigest(dataHashBytes); |
|
|
|
|
|
return new DataNode(sn, key, version, dataHash, bytes); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@Override |
|
|
@Override |
|
|
public int hashCode() { |
|
|
public int hashCode() { |
|
|
return nodeHash.hashCode(); |
|
|
return nodeHash.hashCode(); |
|
|