git / moonbite-core / src/libmw/include/mw/consensus/Weight.h · raw

#pragma once#include <mw/consensus/Params.h>#include <mw/models/tx/TxBody.h>#include <numeric>#include <utility>class Weight{public:    static size_t Calculate(const TxBody& tx_body)    {        size_t input_weight = std::accumulate(            tx_body.GetInputs().begin(), tx_body.GetInputs().end(), (size_t)0,            [](size_t sum, const Input& input) {                return sum + CalcInputWeight(input.GetExtraData());            }        );        size_t kernel_weight = std::accumulate(            tx_body.GetKernels().begin(), tx_body.GetKernels().end(), (size_t)0,            [](size_t sum, const Kernel& kernel) {                size_t kern_weight = CalcKernelWeight(                    kernel.HasStealthExcess(),                    kernel.GetPegOuts(),                    kernel.GetExtraData()                );                return sum + kern_weight;            }        );        size_t output_weight = std::accumulate(            tx_body.GetOutputs().begin(), tx_body.GetOutputs().end(), (size_t)0,            [](size_t sum, const Output& output) {                return sum + CalcOutputWeight(output.HasStandardFields(), output.GetExtraData());            }        );        return input_weight + kernel_weight + output_weight;    }    static bool ExceedsMaximum(const TxBody& tx_body)    {        return tx_body.GetInputs().size() > mw::MAX_NUM_INPUTS || Calculate(tx_body) > mw::MAX_BLOCK_WEIGHT;    }    static size_t CalcInputWeight(const std::vector<uint8_t>& extra_data)    {        return ExtraBytesToWeight(extra_data.size());    }    static size_t CalcKernelWeight(        const bool has_stealth_excess,        const CScript& pegout_script = CScript{},        const std::vector<uint8_t>& extra_data = {})    {        // Kernels with a stealth excess cost extra.        size_t base_weight = has_stealth_excess ? mw::KERNEL_WITH_STEALTH_WEIGHT : mw::BASE_KERNEL_WEIGHT;        return base_weight + ExtraBytesToWeight(pegout_script.size()) + ExtraBytesToWeight(extra_data.size());    }    static size_t CalcKernelWeight(        const bool has_stealth_excess,        const std::vector<PegOutCoin>& pegouts = {},        const std::vector<uint8_t>& extra_data = {})    {        // Kernels with a stealth excess cost extra.        size_t base_weight = has_stealth_excess ? mw::KERNEL_WITH_STEALTH_WEIGHT : mw::BASE_KERNEL_WEIGHT;        size_t pegout_weight = std::accumulate(            pegouts.begin(), pegouts.end(), (size_t)0,            [](size_t sum, const PegOutCoin& pegout) {                return sum + ExtraBytesToWeight(pegout.GetScriptPubKey().size());            }        );        return base_weight + pegout_weight + ExtraBytesToWeight(extra_data.size());    }    // Outputs have a weight of 'BASE_OUTPUT_WEIGHT' plus 2 weight for standard fields, and 1 weight for every 'BYTES_PER_WEIGHT' extra_data bytes    static size_t CalcOutputWeight(const bool standard_fields, const std::vector<uint8_t>& extra_data = {})    {        size_t base_weight = standard_fields ? mw::STANDARD_OUTPUT_WEIGHT : mw::BASE_OUTPUT_WEIGHT;        return base_weight + ExtraBytesToWeight(extra_data.size());    }private:    static size_t ExtraBytesToWeight(const size_t extra_bytes)    {        return (extra_bytes + (mw::BYTES_PER_WEIGHT - 1)) / mw::BYTES_PER_WEIGHT;    }};