network.nerve.base.data.NulsHash Maven / Gradle / Ivy
/*
* MIT License
*
* Copyright (c) 2017-2019 nuls.io
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*/
package network.nerve.base.data;
import network.nerve.base.basic.NulsByteBuffer;
import network.nerve.core.crypto.HexUtil;
import network.nerve.core.crypto.Sha256Hash;
import network.nerve.core.exception.NulsException;
import network.nerve.core.log.Log;
import network.nerve.core.model.ByteUtils;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* @author facjas
*/
public class NulsHash {
public static final NulsHash EMPTY_NULS_HASH = new NulsHash(new byte[32]);
public static final int HASH_LENGTH = 32;
private byte[] bytes;
private String hex;
public NulsHash() {
}
public NulsHash(byte[] bytes) {
this.bytes = bytes;
this.hex = null;
if (bytes.length != HASH_LENGTH) {
throw new RuntimeException("the length is not eq 32 byte");
}
}
public void parse(NulsByteBuffer buffer) throws NulsException {
this.bytes = buffer.readBytes(HASH_LENGTH);
this.hex = null;
}
public String toHex() {
if (null == hex) {
hex = HexUtil.encode(bytes);
}
return hex;
}
public static NulsHash fromHex(String hex) {
byte[] bytes = HexUtil.decode(hex);
return new NulsHash(bytes);
}
public static boolean validHash(String hex) {
try {
fromHex(hex);
return true;
} catch (Exception e) {
return false;
}
}
public boolean verify() {
return this.getBytes() != null && this.getBytes().length == HASH_LENGTH;
}
public static NulsHash calcHash(BaseNulsData data) {
try {
return calcHash(data.serialize());
} catch (Exception e) {
Log.error(e);
return null;
}
}
public byte[] getBytes() {
return bytes;
}
public static NulsHash calcHash(byte[] data) {
NulsHash digestData = new NulsHash();
digestData.bytes = Sha256Hash.hashTwice(data);
return digestData;
}
public static NulsHash calcMerkleHash(List hashList) {
List ddList = new ArrayList<>(hashList);
int levelOffset = 0;
for (int levelSize = ddList.size(); levelSize > 1; levelSize = (levelSize + 1) / 2) {
for (int left = 0; left < levelSize; left += 2) {
int right = Math.min(left + 1, levelSize - 1);
byte[] leftBytes = ByteUtils.reverseBytes(ddList.get(levelOffset + left).getBytes());
byte[] rightBytes = ByteUtils.reverseBytes(ddList.get(levelOffset + right).getBytes());
byte[] whole = new byte[leftBytes.length + rightBytes.length];
System.arraycopy(leftBytes, 0, whole, 0, leftBytes.length);
System.arraycopy(rightBytes, 0, whole, leftBytes.length, rightBytes.length);
NulsHash digest = NulsHash.calcHash(whole);
ddList.add(digest);
}
levelOffset += levelSize;
}
byte[] bytes = ddList.get(ddList.size() - 1).getBytes();
Sha256Hash merkleHash = Sha256Hash.wrap(bytes);
NulsHash digestData = new NulsHash();
digestData.bytes = merkleHash.getBytes();
return digestData;
}
@Override
public int hashCode() {
return Arrays.hashCode(this.bytes);
}
@Override
public boolean equals(final Object obj) {
if (!(obj instanceof NulsHash)) {
return false;
}
final NulsHash rhs = (NulsHash) obj;
return Arrays.equals(this.bytes, rhs.getBytes());
}
public boolean isBlank() {
return this.bytes == null || this.bytes.length == 0;
}
@Override
public String toString() {
return toHex();
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy