/**
* Copyright 2018 VMware
*
* 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.
*/
#ifndef _HOTSTUFF_ENT_H
#define _HOTSTUFF_ENT_H
#include <vector>
#include <unordered_map>
#include <unordered_set>
#include <string>
#include <cstddef>
#include <ios>
#include "salticidae/netaddr.h"
#include "salticidae/ref.h"
#include "hotstuff/type.h"
#include "hotstuff/util.h"
#include "hotstuff/crypto.h"
namespace hotstuff {
enum EntityType {
ENT_TYPE_CMD = 0x0,
ENT_TYPE_BLK = 0x1
};
struct ReplicaInfo {
ReplicaID id;
salticidae::PeerId peer_id;
pubkey_bt pubkey;
ReplicaInfo(ReplicaID id,
const salticidae::PeerId &peer_id,
pubkey_bt &&pubkey):
id(id), peer_id(peer_id), pubkey(std::move(pubkey)) {}
ReplicaInfo(const ReplicaInfo &other):
id(other.id), peer_id(other.peer_id),
pubkey(other.pubkey->clone()) {}
ReplicaInfo(ReplicaInfo &&other):
id(other.id), peer_id(other.peer_id),
pubkey(std::move(other.pubkey)) {}
};
class ReplicaConfig {
std::unordered_map<ReplicaID, ReplicaInfo> replica_map;
public:
size_t nreplicas;
size_t nmajority;
ReplicaConfig(): nreplicas(0), nmajority(0) {}
void add_replica(ReplicaID rid, const ReplicaInfo &info) {
replica_map.insert(std::make_pair(rid, info));
nreplicas++;
}
const ReplicaInfo &get_info(ReplicaID rid) const {
auto it = replica_map.find(rid);
if (it == replica_map.end())
throw HotStuffError("rid %s not found",
get_hex(rid).c_str());
return it->second;
}
const PubKey &get_pubkey(ReplicaID rid) const {
return *(get_info(rid).pubkey);
}
const salticidae::PeerId &get_peer_id(ReplicaID rid) const {
return get_info(rid).peer_id;
}
};
class Block;
class HotStuffCore;
using block_t = salticidae::ArcObj<Block>;
class Command: public Serializable {
friend HotStuffCore;
public:
virtual ~Command() = default;
virtual const uint256_t &get_hash() const = 0;
virtual bool verify() const = 0;
virtual operator std::string () const {
DataStream s;
s << "<cmd id=" << get_hex10(get_hash()) << ">";
return s;
}
};
using command_t = ArcObj<Command>;
template<typename Hashable>
inline static std::vector<uint256_t>
get_hashes(const std::vector<Hashable