NewBlockHashesMessage.java
/*
* Copyright ConsenSys AG.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.besu.ethereum.eth.messages;
import org.hyperledger.besu.datatypes.Hash;
import org.hyperledger.besu.ethereum.p2p.rlpx.wire.AbstractMessageData;
import org.hyperledger.besu.ethereum.p2p.rlpx.wire.MessageData;
import org.hyperledger.besu.ethereum.rlp.BytesValueRLPInput;
import org.hyperledger.besu.ethereum.rlp.BytesValueRLPOutput;
import java.util.Iterator;
import java.util.Objects;
import com.google.common.collect.Iterators;
import org.apache.tuweni.bytes.Bytes;
public final class NewBlockHashesMessage extends AbstractMessageData {
public static NewBlockHashesMessage readFrom(final MessageData message) {
if (message instanceof NewBlockHashesMessage) {
return (NewBlockHashesMessage) message;
}
final int code = message.getCode();
if (code != EthPV62.NEW_BLOCK_HASHES) {
throw new IllegalArgumentException(
String.format("Message has code %d and thus is not a NewBlockHashesMessage.", code));
}
return new NewBlockHashesMessage(message.getData());
}
public static NewBlockHashesMessage create(
final Iterable<NewBlockHashesMessage.NewBlockHash> hashes) {
final BytesValueRLPOutput tmp = new BytesValueRLPOutput();
tmp.startList();
for (final NewBlockHashesMessage.NewBlockHash hash : hashes) {
tmp.startList();
tmp.writeBytes(hash.hash());
tmp.writeLongScalar(hash.number());
tmp.endList();
}
tmp.endList();
return new NewBlockHashesMessage(tmp.encoded());
}
private NewBlockHashesMessage(final Bytes data) {
super(data);
}
@Override
public int getCode() {
return EthPV62.NEW_BLOCK_HASHES;
}
public Iterator<NewBlockHashesMessage.NewBlockHash> getNewHashes() {
return new BytesValueRLPInput(data, false)
.readList(
rlpInput -> {
rlpInput.enterList();
final NewBlockHashesMessage.NewBlockHash res =
new NewBlockHashesMessage.NewBlockHash(
Hash.wrap(rlpInput.readBytes32()), rlpInput.readLongScalar());
rlpInput.leaveList();
return res;
})
.iterator();
}
@Override
public String toStringDecoded() {
return Iterators.toString(getNewHashes());
}
public static final class NewBlockHash {
private final Hash hash;
private final long number;
public NewBlockHash(final Hash hash, final long number) {
this.hash = hash;
this.number = number;
}
public long number() {
return number;
}
public Hash hash() {
return hash;
}
@Override
public String toString() {
return number() + " (" + hash() + ")";
}
@Override
public boolean equals(final Object that) {
if (this == that) {
return true;
}
if (!(that instanceof NewBlockHashesMessage.NewBlockHash)) {
return false;
}
final NewBlockHashesMessage.NewBlockHash other = (NewBlockHashesMessage.NewBlockHash) that;
return other.hash.equals(hash) && other.number == number;
}
@Override
public int hashCode() {
return Objects.hash(hash, number);
}
}
}