eu.bittrade.libs.steemj.protocol.operations.ReportOverProductionOperation.java Source code

Java tutorial

Introduction

Here is the source code for eu.bittrade.libs.steemj.protocol.operations.ReportOverProductionOperation.java

Source

/*
 *     This file is part of SteemJ (formerly known as 'Steem-Java-Api-Wrapper')
 * 
 *     SteemJ is free software: you can redistribute it and/or modify
 *     it under the terms of the GNU General Public License as published by
 *     the Free Software Foundation, either version 3 of the License, or
 *     (at your option) any later version.
 * 
 *     SteemJ is distributed in the hope that it will be useful,
 *     but WITHOUT ANY WARRANTY; without even the implied warranty of
 *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *     GNU General Public License for more details.
 * 
 *     You should have received a copy of the GNU General Public License
 *     along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
 */
package eu.bittrade.libs.steemj.protocol.operations;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.security.InvalidParameterException;
import java.util.Map;

import org.apache.commons.lang3.builder.ToStringBuilder;

import com.fasterxml.jackson.annotation.JsonProperty;

import eu.bittrade.libs.steemj.enums.OperationType;
import eu.bittrade.libs.steemj.enums.PrivateKeyType;
import eu.bittrade.libs.steemj.enums.ValidationType;
import eu.bittrade.libs.steemj.exceptions.SteemInvalidTransactionException;
import eu.bittrade.libs.steemj.interfaces.SignatureObject;
import eu.bittrade.libs.steemj.protocol.AccountName;
import eu.bittrade.libs.steemj.protocol.SignedBlockHeader;
import eu.bittrade.libs.steemj.util.SteemJUtils;

/**
 * This class represents the Steem "report_over_production_operation" object.
 * 
 * @author <a href="http://steemit.com/@dez1337">dez1337</a>
 */
public class ReportOverProductionOperation extends Operation {
    @JsonProperty("reporter")
    private AccountName reporter;
    @JsonProperty("first_block")
    private SignedBlockHeader firstBlock;
    @JsonProperty("second_block")
    private SignedBlockHeader secondBlock;

    /**
     * Create a new report over production operation.
     * 
     * This operation is used to report a miner who signs two blocks at the same
     * time. To be valid, the violation must be reported within
     * STEEMIT_MAX_WITNESSES blocks of the head block (1 round) and the producer
     * must be in the ACTIVE witness set.
     *
     * Users not in the ACTIVE witness set should not have to worry about their
     * key getting compromised and being used to produced multiple blocks so the
     * attacker can report it and steel their vesting steem.
     *
     * The result of the operation is to transfer the full VESTING STEEM balance
     * of the block producer to the reporter.
     * 
     * @param reporter
     *            The miner account (see {@link #setReporter(AccountName)}).
     * @param firstBlock
     *            The first Block (see
     *            {@link #setFirstBlock(SignedBlockHeader)}).
     * @param secondBlock
     *            The second Block (see
     *            {@link #setSecondBlock(SignedBlockHeader)}).
     * @throws InvalidParameterException
     *             If one of the arguments does not fulfill the requirements.
     */
    public ReportOverProductionOperation(@JsonProperty("reporter") AccountName reporter,
            @JsonProperty("first_block") SignedBlockHeader firstBlock,
            @JsonProperty("second_block") SignedBlockHeader secondBlock) {
        super(false);

        this.setReporter(reporter);
        this.setFirstBlock(firstBlock);
        this.setSecondBlock(secondBlock);
    }

    /**
     * Get the account who reported the violation.
     * 
     * @return The account who reported the violation.
     */
    public AccountName getReporter() {
        return reporter;
    }

    /**
     * Set the account who wants to report the violation.
     * 
     * @param reporter
     *            The account who reported the violation.
     * @throws InvalidParameterException
     *             If the reporter is not set.
     */
    public void setReporter(AccountName reporter) {
        this.reporter = SteemJUtils.setIfNotNull(reporter, "The reporter can't be null.");
    }

    /**
     * Get the first block signed by the witness.
     * 
     * @return The first block signed by the witness.
     */
    public SignedBlockHeader getFirstBlock() {
        return firstBlock;
    }

    /**
     * Set the first block signed by the witness.
     * 
     * @param firstBlock
     *            The first block signed by the witness.
     * @throws InvalidParameterException
     *             If the <code>firstBlock</code> is null, does not contain a
     *             valid witness, does not have the same: witness, timestamp or
     *             signee than the <code>secondBlock</code> or if has the same
     *             id than the <code>secondBlock</code>.
     */
    public void setFirstBlock(SignedBlockHeader firstBlock) {
        /*
         * TODO: Implement additional checks:
         * 
         * - first_block.signee() == second_block.signee() - first_block.id() !=
         * second_block.id()
         * 
         * Both checks require that the SignedBlockHeader has the signee() and
         * the id().
         */
        this.firstBlock = SteemJUtils.setIfNotNull(firstBlock, "The provided first block can't be null.");
    }

    /**
     * Get the second block signed by the witness.
     * 
     * @return The second block signed by the witness.
     */
    public SignedBlockHeader getSecondBlock() {
        return secondBlock;
    }

    /**
     * Set the second block signed by the witness.
     * 
     * @param secondBlock
     *            The second block signed by the witness.
     * @throws InvalidParameterException
     *             If the <code>secondBlock</code> is null, does not contain a
     *             valid witness, does not have the same: witness, timestamp or
     *             signee than the <code>firstBlock</code> or if has the same id
     *             than the <code>firstBlock</code>.
     */
    public void setSecondBlock(SignedBlockHeader secondBlock) {
        this.secondBlock = SteemJUtils.setIfNotNull(secondBlock, "The provided second block can't be null.");
    }

    @Override
    public byte[] toByteArray() throws SteemInvalidTransactionException {
        try (ByteArrayOutputStream serializedReportOverProductionOperation = new ByteArrayOutputStream()) {
            serializedReportOverProductionOperation.write(SteemJUtils
                    .transformIntToVarIntByteArray(OperationType.REPORT_OVER_PRODUCTION_OPERATION.getOrderId()));
            serializedReportOverProductionOperation.write(this.getReporter().toByteArray());
            serializedReportOverProductionOperation.write(this.getFirstBlock().toByteArray());
            serializedReportOverProductionOperation.write(this.getSecondBlock().toByteArray());

            return serializedReportOverProductionOperation.toByteArray();
        } catch (IOException e) {
            throw new SteemInvalidTransactionException(
                    "A problem occured while transforming the operation into a byte array.", e);
        }
    }

    @Override
    public String toString() {
        return ToStringBuilder.reflectionToString(this);
    }

    @Override
    public Map<SignatureObject, PrivateKeyType> getRequiredAuthorities(
            Map<SignatureObject, PrivateKeyType> requiredAuthoritiesBase) {
        return requiredAuthoritiesBase;
    }

    @Override
    public void validate(ValidationType validationType) {
        if (!ValidationType.SKIP_VALIDATION.equals(validationType)) {
            if (this.getSecondBlock().getWitness().equals(firstBlock.getWitness())) {
                throw new InvalidParameterException(
                        "The first block witness needs to be the same than the second block witness.");
            } else if (this.getSecondBlock().getTimestamp().equals(firstBlock.getTimestamp())) {
                throw new InvalidParameterException(
                        "The first block timestamp needs to be the same than the second block timestamp.");
            }
            /*
             * TODO: Implement additional checks:
             * 
             * 1. first_block.signee() == second_block.signee() 2.
             * first_block.id() != second_block.id()
             * 
             * Both checks require that the SignedBlockHeader has the signee()
             * and the id().
             */
        }
    }
}