All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.nuls.base.data.BlockHeader Maven / Gradle / Ivy

/*
 * MIT License
 *
 * Copyright (c) 2017-2018 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 io.nuls.base.data;

import io.nuls.base.basic.AddressTool;
import io.nuls.base.basic.NulsByteBuffer;
import io.nuls.base.basic.NulsOutputStreamBuffer;
import io.nuls.base.signture.BlockSignature;
import io.nuls.core.crypto.UnsafeByteArrayOutputStream;
import io.nuls.core.exception.NulsException;
import io.nuls.core.exception.NulsRuntimeException;
import io.nuls.core.parse.SerializeUtils;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Arrays;
import java.util.Comparator;

/**
 * @author vivi
 */
public class BlockHeader extends BaseNulsData {

    /**
     * 区块头排序器
     */
    public static final Comparator BLOCK_HEADER_COMPARATOR = Comparator.comparingLong(BlockHeader::getHeight);

    private transient NulsHash hash;
    private NulsHash preHash;
    private NulsHash merkleHash;
    private long time;
    private long height;
    private int txCount;
    private BlockSignature blockSignature;
    private byte[] extend;
    /**
     * pierre add 智能合约世界状态根
     */
    private transient byte[] stateRoot;

    private transient byte[] packingAddress;

    private synchronized void calcHash() {
        if (null != this.hash) {
            return;
        }
        try {
            hash = NulsHash.calcHash(serializeWithoutSign());
        } catch (Exception e) {
            throw new NulsRuntimeException(e);
        }
    }

    @Override
    public int size() {
        int size = 0;
        size += NulsHash.HASH_LENGTH;               //preHash
        size += NulsHash.HASH_LENGTH;               //merkleHash
        size += SerializeUtils.sizeOfUint32();
        size += SerializeUtils.sizeOfUint32();
        size += SerializeUtils.sizeOfUint32();
        size += SerializeUtils.sizeOfBytes(extend);
        size += SerializeUtils.sizeOfNulsData(blockSignature);
        return size;
    }

    @Override
    protected void serializeToStream(NulsOutputStreamBuffer stream) throws IOException {
        stream.write(preHash.getBytes());
        stream.write(merkleHash.getBytes());
        stream.writeUint32(time);
        stream.writeUint32(height);
        stream.writeUint32(txCount);
        stream.writeBytesWithLength(extend);
        stream.writeNulsData(blockSignature);
    }

    @Override
    public void parse(NulsByteBuffer byteBuffer) throws NulsException {
        this.preHash = byteBuffer.readHash();
        this.merkleHash = byteBuffer.readHash();
        this.time = byteBuffer.readUint32();
        this.height = byteBuffer.readUint32();
        this.txCount = byteBuffer.readInt32();
        this.extend = byteBuffer.readByLengthByte();
        this.blockSignature = byteBuffer.readNulsData(new BlockSignature());
    }

    public byte[] serializeWithoutSign() {
        int size = size() - SerializeUtils.sizeOfNulsData(blockSignature);
        try (ByteArrayOutputStream bos = new UnsafeByteArrayOutputStream(size)) {
            NulsOutputStreamBuffer buffer = new NulsOutputStreamBuffer(bos);
            buffer.write(preHash.getBytes());
            buffer.write(merkleHash.getBytes());
            buffer.writeUint32(time);
            buffer.writeUint32(height);
            buffer.writeUint32(txCount);
            buffer.writeBytesWithLength(extend);
            byte[] bytes = bos.toByteArray();
            if (bytes.length != size) {
                throw new RuntimeException();
            }
            return bytes;
        } catch (IOException e) {
            throw new RuntimeException();
        }
    }

    public NulsHash getHash() {
        if (null == hash) {
            calcHash();
        }
        return hash;
    }

    public void setHash(NulsHash hash) {
        this.hash = hash;
    }

    public NulsHash getPreHash() {
        return preHash;
    }

    public void setPreHash(NulsHash preHash) {
        this.preHash = preHash;
    }

    public NulsHash getMerkleHash() {
        return merkleHash;
    }

    public void setMerkleHash(NulsHash merkleHash) {
        this.merkleHash = merkleHash;
    }

    public long getTime() {
        return time;
    }

    public void setTime(long time) {
        this.time = time;
    }

    public long getHeight() {
        return height;
    }

    public void setHeight(long height) {
        this.height = height;
    }

    public int getTxCount() {
        return txCount;
    }

    public void setTxCount(int txCount) {
        this.txCount = txCount;
    }

    public BlockSignature getBlockSignature() {
        return blockSignature;
    }

    public void setBlockSignature(BlockSignature scriptSign) {
        this.blockSignature = scriptSign;
    }

    public byte[] getPackingAddress(int chainID) {
        if (this.blockSignature != null && this.packingAddress == null) {
            this.packingAddress = AddressTool.getAddress(blockSignature.getPublicKey(), chainID);
        }
        return packingAddress;
    }


    public byte[] getExtend() {
        return extend;
    }

    public void setExtend(byte[] extend) {
        this.extend = extend;
    }

    public void setPackingAddress(byte[] packingAddress) {
        this.packingAddress = packingAddress;
    }

    public byte[] getStateRoot() {
        return stateRoot;
    }

    public void setStateRoot(byte[] stateRoot) {
        this.stateRoot = stateRoot;
    }

    @Override
    public String toString() {
        return "BlockHeader{" +
                "hash=" + hash.toHex() +
                ", preHash=" + preHash.toHex() +
                ", merkleHash=" + merkleHash.toHex() +
                ", time=" + time +
                ", height=" + height +
                ", txCount=" + txCount +
                ", blockSignature=" + blockSignature +
                //", extend=" + Arrays.toString(extend) +
                ", size=" + size() +
                ", packingAddress=" + (packingAddress == null ? packingAddress : AddressTool.getStringAddressByBytes(packingAddress)) +
                '}';
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
            return false;
        }

        BlockHeader header = (BlockHeader) o;

        if (time != header.time) {
            return false;
        }
        if (height != header.height) {
            return false;
        }
        if (txCount != header.txCount) {
            return false;
        }
        if (!preHash.equals(header.preHash)) {
            return false;
        }
        if (!merkleHash.equals(header.merkleHash)) {
            return false;
        }
        if (!blockSignature.equals(header.blockSignature)) {
            return false;
        }
        return Arrays.equals(extend, header.extend);
    }

    @Override
    public int hashCode() {
        int result = preHash.hashCode();
        result = 31 * result + merkleHash.hashCode();
        result = 31 * result + (int) (time ^ (time >>> 32));
        result = 31 * result + (int) (height ^ (height >>> 32));
        result = 31 * result + txCount;
        result = 31 * result + blockSignature.hashCode();
        result = 31 * result + Arrays.hashCode(extend);
        return result;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy