<commit_before>/**
 * Copyright (c) 2014, Matthijs Möhlmann
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *   Redistributions of source code must retain the above copyright notice, this
 *   list of conditions and the following disclaimer.
 *
 *   Redistributions in binary form must reproduce the above copyright notice,
 *   this list of conditions and the following disclaimer in the documentation
 *   and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#include <sqlpp11/postgresql/bind_result.h>
#include <sqlpp11/exception.h>

#include <iostream>
#include <sstream>

#include "detail/prepared_statement_handle.h"

namespace sqlpp {

	namespace postgresql {

		bind_result_t::bind_result_t(const std::shared_ptr<detail::prepared_statement_handle_t> &handle) : _handle(handle) {
			if (this->_handle && this->_handle->debug) {

				// cerr
				std::cerr << "PostgreSQL debug: constructing bind result, using handle at: " << this->_handle.get() << std::endl;
			}
		}

		bool bind_result_t::next_impl() {
			if (_handle->debug) {
				std::cerr << "PostgreSQL debug: accessing next row of handle at " << _handle.get() << std::endl;
			}

			// Fetch total amount
			if (_handle->totalCount == 0U) {
				_handle->totalCount = PQntuples(_handle->result);
			} else {

				// Next row
				if (_handle->count < (_handle->totalCount - 1)) {
					_handle->count++;
				} else {
					return false;
				}
			}

			// Really needed?
			if (_handle->fields == 0U) {
				_handle->fields = PQnfields(_handle->result);
			}

			return true;
		}

		void bind_result_t::_bind_boolean_result(size_t index, signed char *value, bool *is_null) {
			if (_handle->debug) {
				std::cerr << "PostgreSQL debug: binding boolean result at index: " << index << std::endl;
			}
			if (index > _handle->fields) {
				throw sqlpp::exception("PostgreSQL error: index out of range");
			}

			// Assign value
			std::istringstream in(PQgetvalue(_handle->result, _handle->count, index));
			in >> *value;
			*is_null = PQgetisnull(_handle->result, _handle->count, index);
		}

		void bind_result_t::_bind_floating_point_result(size_t index, double *value, bool *is_null) {
			if (_handle->debug) {
				std::cerr << "PostgreSQL debug: binding floating_point result at index: " << index << std::endl;
			}
			if (index > _handle->fields) {
				throw sqlpp::exception("PostgreSQL error: index out of range");
			}

			std::istringstream in(PQgetvalue(_handle->result, _handle->count, index));
			in >> *value;
			*is_null = PQgetisnull(_handle->result, _handle->count, index);
		}

		void bind_result_t::_bind_integral_result(size_t index, int64_t *value, bool *is_null) {
			if (_handle->debug) {
				std::cerr << "PostgreSQL debug: binding integral result at index: " << index << std::endl;
			}
			if (index > _handle->fields) {
				throw sqlpp::exception("PostgreSQL error: index out of range");
			}

			std::istringstream in(PQgetvalue(_handle->result, _handle->count, index));
			in >> *value;
			*is_null = PQgetisnull(_handle->result, _handle->count, index);
		}

		void bind_result_t::_bind_text_result(size_t index, const char **value, size_t *len) {
			if (_handle->debug) {
				std::cerr << "PostgreSQL debug: binding text result at index: " << index << std::endl;
			}
			if (index > _handle->fields) {
				throw sqlpp::exception("PostgreSQL error: index out of range");
			}

			*value = const_cast<const char *>(PQgetvalue(_handle->result, _handle->count, index));
			*len = PQgetlength(_handle->result, _handle->count, index);
		}
	}
}

<commit_msg>Fix error with a query returning an empty result set: row number 0 is out of range 0..-1<commit_after>/**
 * Copyright (c) 2014, Matthijs Möhlmann
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *   Redistributions of source code must retain the above copyright notice, this
 *   list of conditions and the following disclaimer.
 *
 *   Redistributions in binary form must reproduce the above copyright notice,
 *   this list of conditions and the following disclaimer in the documentation
 *   and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#include <sqlpp11/postgresql/bind_result.h>
#include <sqlpp11/exception.h>

#include <iostream>
#include <sstream>

#include "detail/prepared_statement_handle.h"

namespace sqlpp {

	namespace postgresql {

		bind_result_t::bind_result_t(const std::shared_ptr<detail::prepared_statement_handle_t> &handle) : _handle(handle) {
			if (this->_handle && this->_handle->debug) {

				// cerr
				std::cerr << "PostgreSQL debug: constructing bind result, using handle at: " << this->_handle.get() << std::endl;
			}
		}

		bool bind_result_t::next_impl() {
			if (_handle->debug) {
				std::cerr << "PostgreSQL debug: accessing next row of handle at " << _handle.get() << std::endl;
			}

			// Fetch total amount
			if (_handle->totalCount == 0U) {
				_handle->totalCount = PQntuples(_handle->result);
				if (_handle->totalCount == 0U)
					return false;
			} else {

				// Next row
				if (_handle->count < (_handle->totalCount - 1)) {
					_handle->count++;
				} else {
					return false;
				}
			}

			// Really needed?
			if (_handle->fields == 0U) {
				_handle->fields = PQnfields(_handle->result);
			}

			return true;
		}

		void bind_result_t::_bind_boolean_result(size_t index, signed char *value, bool *is_null) {
			if (_handle->debug) {
				std::cerr << "PostgreSQL debug: binding boolean result at index: " << index << std::endl;
			}
			if (index > _handle->fields) {
				throw sqlpp::exception("PostgreSQL error: index out of range");
			}

			// Assign value
			std::istringstream in(PQgetvalue(_handle->result, _handle->count, index));
			in >> *value;
			*is_null = PQgetisnull(_handle->result, _handle->count, index);
		}

		void bind_result_t::_bind_floating_point_result(size_t index, double *value, bool *is_null) {
			if (_handle->debug) {
				std::cerr << "PostgreSQL debug: binding floating_point result at index: " << index << std::endl;
			}
			if (index > _handle->fields) {
				throw sqlpp::exception("PostgreSQL error: index out of range");
			}

			std::istringstream in(PQgetvalue(_handle->result, _handle->count, index));
			in >> *value;
			*is_null = PQgetisnull(_handle->result, _handle->count, index);
		}

		void bind_result_t::_bind_integral_result(size_t index, int64_t *value, bool *is_null) {
			if (_handle->debug) {
				std::cerr << "PostgreSQL debug: binding integral result at index: " << index << std::endl;
			}
			if (index > _handle->fields) {
				throw sqlpp::exception("PostgreSQL error: index out of range");
			}

			std::istringstream in(PQgetvalue(_handle->result, _handle->count, index));
			in >> *value;
			*is_null = PQgetisnull(_handle->result, _handle->count, index);
		}

		void bind_result_t::_bind_text_result(size_t index, const char **value, size_t *len) {
			if (_handle->debug) {
				std::cerr << "PostgreSQL debug: binding text result at index: " << index << std::endl;
			}
			if (index > _handle->fields) {
				throw sqlpp::exception("PostgreSQL error: index out of range");
			}

			*value = const_cast<const char *>(PQgetvalue(_handle->result, _handle->count, index));
			*len = PQgetlength(_handle->result, _handle->count, index);
		}
	}
}

<|endoftext|>


<commit_before>#include <mk_test.h>

#include <algorithm>
#include "../src/XmlElement.hpp"

using namespace Xml;

int
main()
{
    std::string name = "test";
    std::string tag  = "root";

    Element e(name);

    test_assert(e.name() == name);
    e.setName(tag);
    test_assert(e.name() == tag);

    auto c1 = new Element("child1");
    auto c2 = new Element("child2");

    e.append(c1);
    e.append(c2);

    test_assert(c1->parent() == &e);
    test_assert(c1->parentElement() == &e);
    test_assert(c2->parent() == &e);
    test_assert(c2->parentElement() == &e);

    test_assert(e.isElement());
    test_assert(c1->isElement());
    test_assert(c2->isElement());

    test_assert(e.elements().size() == 2);
    test_assert(e.elements()[0] == c1);
    test_assert(e.elements()[1] == c2);

    std::string text = "This is a text in root.";

    e.appendText(text);
    test_assert(e.text() == text);

    std::string attr1 = "attr1";
    std::string attr2 = "attr2";
    std::string value1 = "value1";
    std::string value2 = "value2";

    c1->setAttribute(attr1, value1);
    c1->setAttribute(attr2, value2);

    test_assert(c1->attribute(attr1) == value1);
    test_assert(c1->attribute(attr2) == value2);

    std::string text1 = "This is a text in child 1.";
    std::string text2 = "This is a text in child 2.";
    c1->appendText(text1);
    c2->appendText(text2);

    test_assert(c1->text() == text1);
    test_assert(c2->text() == text2);

    c1->appendComment("This is a comment.");
    c1->appendComment("This is another comment.");

    auto c3 = new Element("child1.1");
    std::string text3 = "This is a text in child 1.1.";
    c3->appendText(text3);
    c3->appendComment("Yet another comment.");
    c1->append(c3);

    std::cerr << e << std::endl;

    auto const children = e.children();
    test_assert(std::find(std::begin(children), std::end(children), c1) != std::end(children));
    e.remove(c1);
    auto const children2 = e.children();
    test_assert(std::find(std::begin(children2), std::end(children2), c1) == std::end(children2));

    e.setContent("Foo");
    test_assert(e.text() == "Foo");

    e.clearContent();
    test_assert(e.text() == "");
    test_assert(e.elements().size() == 0);

    return 0;
}
<commit_msg>Fixed element tests<commit_after>#include <mk_test.h>

#include <algorithm>
#include "../src/XmlElement.hpp"

using namespace Xml;

int
main()
{
    std::string name = "test";
    std::string tag  = "root";

    Element e(name);

    test_assert(e.name() == name);
    e.setName(tag);
    test_assert(e.name() == tag);

    auto c1 = new Element("child1");
    auto c2 = new Element("child2");

    e.append(c1);
    e.append(c2);

    test_assert(c1->parent() == &e);
    test_assert(c1->parentElement() == &e);
    test_assert(c2->parent() == &e);
    test_assert(c2->parentElement() == &e);

    test_assert(e.elements().size() == 2);
    test_assert(e.elements()[0] == c1);
    test_assert(e.elements()[1] == c2);

    std::string text = "This is a text in root.";

    e.appendText(text);
    test_assert(e.text() == text);

    std::string attr1 = "attr1";
    std::string attr2 = "attr2";
    std::string value1 = "value1";
    std::string value2 = "value2";

    c1->setAttribute(attr1, value1);
    c1->setAttribute(attr2, value2);

    test_assert(c1->attribute(attr1) == value1);
    test_assert(c1->attribute(attr2) == value2);

    std::string text1 = "This is a text in child 1.";
    std::string text2 = "This is a text in child 2.";
    c1->appendText(text1);
    c2->appendText(text2);

    test_assert(c1->text() == text1);
    test_assert(c2->text() == text2);

    c1->appendComment("This is a comment.");
    c1->appendComment("This is another comment.");

    auto c3 = new Element("child1.1");
    std::string text3 = "This is a text in child 1.1.";
    c3->appendText(text3);
    c3->appendComment("Yet another comment.");
    c1->append(c3);

    std::cerr << e << std::endl;

    auto const children = e.children();
    test_assert(std::find(std::begin(children), std::end(children), c1) != std::end(children));
    e.remove(c1);
    auto const children2 = e.children();
    test_assert(std::find(std::begin(children2), std::end(children2), c1) == std::end(children2));

    e.setContent("Foo");
    test_assert(e.text() == "Foo");

    e.clearContent();
    test_assert(e.text() == "");
    test_assert(e.elements().size() == 0);

    return 0;
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2017 Facebook, Inc.
 *
 * 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.
 */

#include <map>
#include <string>
#include <tuple>
#include <vector>

#include <llvm/DebugInfo/DWARF/DWARFContext.h>
#include <llvm/DebugInfo/DWARF/DWARFDebugLine.h>
#include <llvm/IR/Module.h>
#include <llvm/MC/MCAsmInfo.h>
#include <llvm/MC/MCContext.h>
#include <llvm/MC/MCDisassembler/MCDisassembler.h>
#include <llvm/MC/MCInstPrinter.h>
#include <llvm/MC/MCInstrInfo.h>
#include <llvm/MC/MCObjectFileInfo.h>
#include <llvm/MC/MCRegisterInfo.h>
#include <llvm/Support/TargetRegistry.h>

#include "bcc_debug.h"

namespace ebpf {

// ld_pseudo can only be disassembled properly
// in llvm 6.0, so having this workaround now
// until disto llvm versions catch up
#define WORKAROUND_FOR_LD_PSEUDO

using std::get;
using std::map;
using std::string;
using std::tuple;
using std::vector;
using namespace llvm;
using DWARFLineTable = DWARFDebugLine::LineTable;

void SourceDebugger::adjustInstSize(uint64_t &Size, uint8_t byte0,
                                    uint8_t byte1) {
#ifdef WORKAROUND_FOR_LD_PSEUDO
  bool isLittleEndian = mod_->getDataLayout().isLittleEndian();
  if (byte0 == 0x18 && ((isLittleEndian && (byte1 & 0xf) == 0x1) ||
                        (!isLittleEndian && (byte1 & 0xf0) == 0x10)))
    Size = 16;
#endif
}

vector<string> SourceDebugger::buildLineCache() {
  vector<string> LineCache;
  size_t FileBufSize = mod_src_.size();

  for (uint32_t start = 0, end = start; end < FileBufSize; end++)
    if (mod_src_[end] == '\n' || end == FileBufSize - 1 ||
        (mod_src_[end] == '\r' && mod_src_[end + 1] == '\n')) {
      // Not including the endline
      LineCache.push_back(string(mod_src_.substr(start, end - start)));
      if (mod_src_[end] == '\r')
        end++;
      start = end + 1;
    }

  return LineCache;
}

void SourceDebugger::dumpSrcLine(const vector<string> &LineCache,
                                 const string &FileName, uint32_t Line,
                                 uint32_t &CurrentSrcLine,
                                 llvm::raw_ostream &os) {
  if (Line != 0 && Line != CurrentSrcLine && Line < LineCache.size() &&
      FileName == mod_->getSourceFileName()) {
    os << "; " << StringRef(LineCache[Line - 1]).ltrim()
       << format(
              " // Line"
              "%4" PRIu64 "\n",
              Line);
    CurrentSrcLine = Line;
  }
}

void SourceDebugger::getDebugSections(
    StringMap<std::unique_ptr<MemoryBuffer>> &DebugSections) {
  for (auto section : sections_) {
    if (strncmp(section.first.c_str(), ".debug", 6) == 0) {
      StringRef SecData(reinterpret_cast<const char *>(get<0>(section.second)),
                        get<1>(section.second));
      DebugSections[section.first.substr(1)] =
          MemoryBuffer::getMemBufferCopy(SecData);
    }
  }
}

void SourceDebugger::dump() {
  string Error;
  string TripleStr(mod_->getTargetTriple());
  Triple TheTriple(TripleStr);
  const Target *T = TargetRegistry::lookupTarget(TripleStr, Error);
  if (!T) {
    errs() << "Debug Error: cannot get target\n";
    return;
  }

  std::unique_ptr<MCRegisterInfo> MRI(T->createMCRegInfo(TripleStr));
  if (!MRI) {
    errs() << "Debug Error: cannot get register info\n";
    return;
  }
#if LLVM_MAJOR_VERSION >= 10
  MCTargetOptions MCOptions;
  std::unique_ptr<MCAsmInfo> MAI(T->createMCAsmInfo(*MRI, TripleStr, MCOptions));
#else
  std::unique_ptr<MCAsmInfo> MAI(T->createMCAsmInfo(*MRI, TripleStr));
#endif
  if (!MAI) {
    errs() << "Debug Error: cannot get assembly info\n";
    return;
  }

  std::unique_ptr<MCSubtargetInfo> STI(
      T->createMCSubtargetInfo(TripleStr, "", ""));
  MCObjectFileInfo MOFI;
#if LLVM_MAJOR_VERSION >= 13
  MCContext Ctx(TheTriple, MAI.get(), MRI.get(), &MOFI, STI.get(), nullptr);
  MOFI.initMCObjectFileInfo(Ctx, false, false);
#else
  MCContext Ctx(MAI.get(), MRI.get(), &MOFI, nullptr);
  MOFI.InitMCObjectFileInfo(TheTriple, false, Ctx, false);
#endif

  std::unique_ptr<MCInstrInfo> MCII(T->createMCInstrInfo());
  MCInstPrinter *IP = T->createMCInstPrinter(TheTriple, 0, *MAI, *MCII, *MRI);
  if (!IP) {
    errs() << "Debug Error: unable to create instruction printer\n";
    return;
  }

  std::unique_ptr<const MCDisassembler> DisAsm(
      T->createMCDisassembler(*STI, Ctx));
  if (!DisAsm) {
    errs() << "Debug Error: no disassembler\n";
    return;
  }

  // Set up the dwarf debug context
  StringMap<std::unique_ptr<MemoryBuffer>> DebugSections;
  getDebugSections(DebugSections);
  std::unique_ptr<DWARFContext> DwarfCtx =
      DWARFContext::create(DebugSections, 8);
  if (!DwarfCtx) {
    errs() << "Debug Error: dwarf context creation failed\n";
    return;
  }

  // bcc has only one compilation unit
  // getCompileUnitAtIndex() was gone in llvm 8.0 (https://reviews.llvm.org/D49741)
#if LLVM_MAJOR_VERSION >= 8
  DWARFCompileUnit *CU = cast<DWARFCompileUnit>(DwarfCtx->getUnitAtIndex(0));
#else
  DWARFCompileUnit *CU = DwarfCtx->getCompileUnitAtIndex(0);
#endif
  if (!CU) {
    errs() << "Debug Error: dwarf context failed to get compile unit\n";
    return;
  }

  const DWARFLineTable *LineTable = DwarfCtx->getLineTableForUnit(CU);
  if (!LineTable) {
    errs() << "Debug Error: dwarf context failed to get line table\n";
    return;
  }

  // Build LineCache for later source code printing
  vector<string> LineCache = buildLineCache();

  // Start to disassemble with source code annotation section by section
  for (auto section : sections_)
    if (!strncmp(fn_prefix_.c_str(), section.first.c_str(),
                 fn_prefix_.size())) {
      MCDisassembler::DecodeStatus S;
      MCInst Inst;
      uint64_t Size;
      uint8_t *FuncStart = get<0>(section.second);
      uint64_t FuncSize = get<1>(section.second);
#if LLVM_MAJOR_VERSION >= 9
      unsigned SectionID = get<2>(section.second);
#endif
      ArrayRef<uint8_t> Data(FuncStart, FuncSize);
      uint32_t CurrentSrcLine = 0;
      string func_name = section.first.substr(fn_prefix_.size());

      errs() << "Disassembly of section " << section.first << ":\n"
             << func_name << ":\n";

      string src_dbg_str;
      llvm::raw_string_ostream os(src_dbg_str);
      for (uint64_t Index = 0; Index < FuncSize; Index += Size) {
#if LLVM_MAJOR_VERSION >= 10
        S = DisAsm->getInstruction(Inst, Size, Data.slice(Index), Index,
                                   nulls());
#else
        S = DisAsm->getInstruction(Inst, Size, Data.slice(Index), Index,
                                   nulls(), nulls());
#endif
        if (S != MCDisassembler::Success) {
          os << "Debug Error: disassembler failed: " << std::to_string(S)
             << '\n';
          break;
        } else {
          DILineInfo LineInfo;

          LineTable->getFileLineInfoForAddress(
#if LLVM_MAJOR_VERSION >= 9
              {(uint64_t)FuncStart + Index, SectionID},
#else
              (uint64_t)FuncStart + Index,
#endif
              CU->getCompilationDir(),
              DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath,
              LineInfo);

          adjustInstSize(Size, Data[Index], Data[Index + 1]);
          dumpSrcLine(LineCache, LineInfo.FileName, LineInfo.Line,
                      CurrentSrcLine, os);
          os << format("%4" PRIu64 ":", Index >> 3) << '\t';
          dumpBytes(Data.slice(Index, Size), os);
#if LLVM_MAJOR_VERSION >= 10
          IP->printInst(&Inst, 0, "", *STI, os);
#else
          IP->printInst(&Inst, os, "", *STI);
#endif
          os << '\n';
        }
      }
      os.flush();
      errs() << src_dbg_str << '\n';
      src_dbg_fmap_[func_name] = src_dbg_str;
    }
}

}  // namespace ebpf
<commit_msg>Fix a llvm compilation error<commit_after>/*
 * Copyright (c) 2017 Facebook, Inc.
 *
 * 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.
 */

#include <map>
#include <string>
#include <tuple>
#include <vector>

#include <llvm/DebugInfo/DWARF/DWARFContext.h>
#include <llvm/DebugInfo/DWARF/DWARFDebugLine.h>
#include <llvm/IR/Module.h>
#include <llvm/MC/MCAsmInfo.h>
#include <llvm/MC/MCContext.h>
#include <llvm/MC/MCDisassembler/MCDisassembler.h>
#include <llvm/MC/MCInstPrinter.h>
#include <llvm/MC/MCInstrInfo.h>
#include <llvm/MC/MCObjectFileInfo.h>
#include <llvm/MC/MCRegisterInfo.h>
#include <llvm/Support/TargetRegistry.h>

#include "bcc_debug.h"

namespace ebpf {

// ld_pseudo can only be disassembled properly
// in llvm 6.0, so having this workaround now
// until disto llvm versions catch up
#define WORKAROUND_FOR_LD_PSEUDO

using std::get;
using std::map;
using std::string;
using std::tuple;
using std::vector;
using namespace llvm;
using DWARFLineTable = DWARFDebugLine::LineTable;

void SourceDebugger::adjustInstSize(uint64_t &Size, uint8_t byte0,
                                    uint8_t byte1) {
#ifdef WORKAROUND_FOR_LD_PSEUDO
  bool isLittleEndian = mod_->getDataLayout().isLittleEndian();
  if (byte0 == 0x18 && ((isLittleEndian && (byte1 & 0xf) == 0x1) ||
                        (!isLittleEndian && (byte1 & 0xf0) == 0x10)))
    Size = 16;
#endif
}

vector<string> SourceDebugger::buildLineCache() {
  vector<string> LineCache;
  size_t FileBufSize = mod_src_.size();

  for (uint32_t start = 0, end = start; end < FileBufSize; end++)
    if (mod_src_[end] == '\n' || end == FileBufSize - 1 ||
        (mod_src_[end] == '\r' && mod_src_[end + 1] == '\n')) {
      // Not including the endline
      LineCache.push_back(string(mod_src_.substr(start, end - start)));
      if (mod_src_[end] == '\r')
        end++;
      start = end + 1;
    }

  return LineCache;
}

void SourceDebugger::dumpSrcLine(const vector<string> &LineCache,
                                 const string &FileName, uint32_t Line,
                                 uint32_t &CurrentSrcLine,
                                 llvm::raw_ostream &os) {
  if (Line != 0 && Line != CurrentSrcLine && Line < LineCache.size() &&
      FileName == mod_->getSourceFileName()) {
    os << "; " << StringRef(LineCache[Line - 1]).ltrim()
       << format(
              " // Line"
              "%4" PRIu64 "\n",
              Line);
    CurrentSrcLine = Line;
  }
}

void SourceDebugger::getDebugSections(
    StringMap<std::unique_ptr<MemoryBuffer>> &DebugSections) {
  for (auto section : sections_) {
    if (strncmp(section.first.c_str(), ".debug", 6) == 0) {
      StringRef SecData(reinterpret_cast<const char *>(get<0>(section.second)),
                        get<1>(section.second));
      DebugSections[section.first.substr(1)] =
          MemoryBuffer::getMemBufferCopy(SecData);
    }
  }
}

void SourceDebugger::dump() {
  string Error;
  string TripleStr(mod_->getTargetTriple());
  Triple TheTriple(TripleStr);
  const Target *T = TargetRegistry::lookupTarget(TripleStr, Error);
  if (!T) {
    errs() << "Debug Error: cannot get target\n";
    return;
  }

  std::unique_ptr<MCRegisterInfo> MRI(T->createMCRegInfo(TripleStr));
  if (!MRI) {
    errs() << "Debug Error: cannot get register info\n";
    return;
  }
#if LLVM_MAJOR_VERSION >= 10
  MCTargetOptions MCOptions;
  std::unique_ptr<MCAsmInfo> MAI(T->createMCAsmInfo(*MRI, TripleStr, MCOptions));
#else
  std::unique_ptr<MCAsmInfo> MAI(T->createMCAsmInfo(*MRI, TripleStr));
#endif
  if (!MAI) {
    errs() << "Debug Error: cannot get assembly info\n";
    return;
  }

  std::unique_ptr<MCSubtargetInfo> STI(
      T->createMCSubtargetInfo(TripleStr, "", ""));
  MCObjectFileInfo MOFI;
#if LLVM_MAJOR_VERSION >= 13
  MCContext Ctx(TheTriple, MAI.get(), MRI.get(), STI.get(), nullptr);
  Ctx.setObjectFileInfo(&MOFI);
  MOFI.initMCObjectFileInfo(Ctx, false, false);
#else
  MCContext Ctx(MAI.get(), MRI.get(), &MOFI, nullptr);
  MOFI.InitMCObjectFileInfo(TheTriple, false, Ctx, false);
#endif

  std::unique_ptr<MCInstrInfo> MCII(T->createMCInstrInfo());
  MCInstPrinter *IP = T->createMCInstPrinter(TheTriple, 0, *MAI, *MCII, *MRI);
  if (!IP) {
    errs() << "Debug Error: unable to create instruction printer\n";
    return;
  }

  std::unique_ptr<const MCDisassembler> DisAsm(
      T->createMCDisassembler(*STI, Ctx));
  if (!DisAsm) {
    errs() << "Debug Error: no disassembler\n";
    return;
  }

  // Set up the dwarf debug context
  StringMap<std::unique_ptr<MemoryBuffer>> DebugSections;
  getDebugSections(DebugSections);
  std::unique_ptr<DWARFContext> DwarfCtx =
      DWARFContext::create(DebugSections, 8);
  if (!DwarfCtx) {
    errs() << "Debug Error: dwarf context creation failed\n";
    return;
  }

  // bcc has only one compilation unit
  // getCompileUnitAtIndex() was gone in llvm 8.0 (https://reviews.llvm.org/D49741)
#if LLVM_MAJOR_VERSION >= 8
  DWARFCompileUnit *CU = cast<DWARFCompileUnit>(DwarfCtx->getUnitAtIndex(0));
#else
  DWARFCompileUnit *CU = DwarfCtx->getCompileUnitAtIndex(0);
#endif
  if (!CU) {
    errs() << "Debug Error: dwarf context failed to get compile unit\n";
    return;
  }

  const DWARFLineTable *LineTable = DwarfCtx->getLineTableForUnit(CU);
  if (!LineTable) {
    errs() << "Debug Error: dwarf context failed to get line table\n";
    return;
  }

  // Build LineCache for later source code printing
  vector<string> LineCache = buildLineCache();

  // Start to disassemble with source code annotation section by section
  for (auto section : sections_)
    if (!strncmp(fn_prefix_.c_str(), section.first.c_str(),
                 fn_prefix_.size())) {
      MCDisassembler::DecodeStatus S;
      MCInst Inst;
      uint64_t Size;
      uint8_t *FuncStart = get<0>(section.second);
      uint64_t FuncSize = get<1>(section.second);
#if LLVM_MAJOR_VERSION >= 9
      unsigned SectionID = get<2>(section.second);
#endif
      ArrayRef<uint8_t> Data(FuncStart, FuncSize);
      uint32_t CurrentSrcLine = 0;
      string func_name = section.first.substr(fn_prefix_.size());

      errs() << "Disassembly of section " << section.first << ":\n"
             << func_name << ":\n";

      string src_dbg_str;
      llvm::raw_string_ostream os(src_dbg_str);
      for (uint64_t Index = 0; Index < FuncSize; Index += Size) {
#if LLVM_MAJOR_VERSION >= 10
        S = DisAsm->getInstruction(Inst, Size, Data.slice(Index), Index,
                                   nulls());
#else
        S = DisAsm->getInstruction(Inst, Size, Data.slice(Index), Index,
                                   nulls(), nulls());
#endif
        if (S != MCDisassembler::Success) {
          os << "Debug Error: disassembler failed: " << std::to_string(S)
             << '\n';
          break;
        } else {
          DILineInfo LineInfo;

          LineTable->getFileLineInfoForAddress(
#if LLVM_MAJOR_VERSION >= 9
              {(uint64_t)FuncStart + Index, SectionID},
#else
              (uint64_t)FuncStart + Index,
#endif
              CU->getCompilationDir(),
              DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath,
              LineInfo);

          adjustInstSize(Size, Data[Index], Data[Index + 1]);
          dumpSrcLine(LineCache, LineInfo.FileName, LineInfo.Line,
                      CurrentSrcLine, os);
          os << format("%4" PRIu64 ":", Index >> 3) << '\t';
          dumpBytes(Data.slice(Index, Size), os);
#if LLVM_MAJOR_VERSION >= 10
          IP->printInst(&Inst, 0, "", *STI, os);
#else
          IP->printInst(&Inst, os, "", *STI);
#endif
          os << '\n';
        }
      }
      os.flush();
      errs() << src_dbg_str << '\n';
      src_dbg_fmap_[func_name] = src_dbg_str;
    }
}

}  // namespace ebpf
<|endoftext|>


<commit_before>#include "Config.hxx"
#include "CertDatabase.hxx"
#include "Wildcard.hxx"
#include "ssl/Util.hxx"
#include "ssl/Name.hxx"
#include "ssl/MemBio.hxx"
#include "ssl/Unique.hxx"
#include "pg/Error.hxx"
#include "util/ConstBuffer.hxx"

#include <inline/compiler.h>

#include <openssl/ts.h>

#include <stdexcept>

#include <stdio.h>
#include <stdlib.h>
#include <poll.h>

static const CertDatabaseConfig config{"dbname=lb", std::string()};

static PgResult
CheckError(PgResult &&result)
{
    if (result.IsError())
        throw PgError(std::move(result));

    return std::move(result);
}

gcc_pure
static AllocatedString<>
GetCommonName(X509_NAME &name)
{
    return NidToString(name, NID_commonName);
}

gcc_pure
static AllocatedString<>
GetCommonName(X509 *cert)
{
    X509_NAME *subject = X509_get_subject_name(cert);
    return subject != nullptr
        ? GetCommonName(*subject)
        : nullptr;
}

gcc_pure
static AllocatedString<>
FormatTime(ASN1_TIME *t)
{
    if (t == nullptr)
        return nullptr;

    return BioWriterToString([t](BIO &bio){
            ASN1_TIME_print(&bio, t);
        });
}

static int
LoadCertificate(const char *cert_path, const char *key_path)
{
    X509 *cert = TS_CONF_load_cert(cert_path);
    if (cert == nullptr) {
        fprintf(stderr, "Failed to load certificate\n");
        return EXIT_FAILURE;
    }

    const auto common_name = GetCommonName(cert);
    if (common_name == nullptr) {
        fprintf(stderr, "Certificate has no common name\n");
        return EXIT_FAILURE;
    }

    auto key = TS_CONF_load_key(key_path, nullptr);
    if (key == nullptr) {
        fprintf(stderr, "Failed to load key\n");
        return EXIT_FAILURE;
    }

    if (!MatchModulus(*cert, *key)) {
        fprintf(stderr, "Key and certificate do not match.\n");
        return EXIT_FAILURE;
    }

    CertDatabase db(config);

    unsigned char *cert_der_buffer = nullptr;
    int cert_der_length = i2d_X509(cert, &cert_der_buffer);
    if (cert_der_length < 0) {
        fprintf(stderr, "Failed to encode certificate\n");
        return EXIT_FAILURE;
    }

    const PgBinaryValue cert_der(cert_der_buffer, cert_der_length);

    unsigned char *key_der_buffer = nullptr;
    int key_der_length = i2d_PrivateKey(key, &key_der_buffer);
    if (key_der_length < 0) {
        fprintf(stderr, "Failed to encode key\n");
        return EXIT_FAILURE;
    }

    const PgBinaryValue key_der(key_der_buffer, key_der_length);

    const auto not_before = FormatTime(X509_get_notBefore(cert));
    if (not_before == nullptr) {
        fprintf(stderr, "Certificate does not have a notBefore time stamp\n");
        return EXIT_FAILURE;
    }

    const auto not_after = FormatTime(X509_get_notAfter(cert));
    if (not_after == nullptr) {
        fprintf(stderr, "Certificate does not have a notAfter time stamp\n");
        return EXIT_FAILURE;
    }

    auto result = CheckError(db.UpdateServerCertificate(common_name.c_str(),
                                                        not_before.c_str(),
                                                        not_after.c_str(),
                                                        cert_der, key_der));
    if (result.GetAffectedRows() > 0) {
        printf("update: %s\n", common_name.c_str());
    } else {
        CheckError(db.InsertServerCertificate(common_name.c_str(),
                                              not_before.c_str(),
                                              not_after.c_str(),
                                              cert_der, key_der));
        printf("insert: %s\n", common_name.c_str());
    }

    db.NotifyModified();

    return EXIT_SUCCESS;
}

static int
DeleteCertificate(const char *host)
{
    CertDatabase db(config);

    const auto result = CheckError(db.DeleteServerCertificateByCommonName(host));
    if (result.GetAffectedRows() == 0)
        throw "Certificate not found";

    return EXIT_SUCCESS;
}

static UniqueX509
FindCertByCommonName(CertDatabase &db, const char *common_name)
{
    auto result = CheckError(db.FindServerCertificateByCommonName(common_name));
    if (result.GetRowCount() == 0)
        return nullptr;

    if (!result.IsColumnBinary(0) || result.IsValueNull(0, 0))
        throw "Unexpected result";

    auto cert_der = result.GetBinaryValue(0, 0);

    auto data = (const unsigned char *)cert_der.value;
    UniqueX509 cert(d2i_X509(nullptr, &data, cert_der.size));
    if (!cert)
        throw "d2i_X509() failed";

    return cert;
}

static UniqueX509
FindCertByHost(const char *host)
{
    CertDatabase db(config);

    auto cert = FindCertByCommonName(db, host);
    if (!cert) {
        auto wildcard = MakeCommonNameWildcard(host);
        if (!wildcard.empty())
            cert = FindCertByCommonName(db, wildcard.c_str());

        if (!cert)
            throw "Certificate not found";
    }

    return cert;
}

static int
FindCertificate(const char *host)
{
    auto cert = FindCertByHost(host);
    X509_print_fp(stdout, cert.get());
    PEM_write_X509(stdout, cert.get());
    return EXIT_SUCCESS;
}

static int
Monitor()
{
    CertDatabase db(config);
    CheckError(db.ListenModified());

    std::string last_modified = db.GetLastModified();
    if (last_modified.empty()) {
        last_modified = db.GetCurrentTimestamp();
        if (last_modified.empty())
            throw "CURRENT_TIMESTAMP failed";
    }

    struct pollfd pfd = {
        .fd = db.GetSocket(),
        .events = POLLIN,
    };

    while (true) {
        if (poll(&pfd, 1, -1) < 0)
            throw "poll() failed";

        db.ConsumeInput();
        while (db.GetNextNotify()) {}

        std::string new_last_modified = db.GetLastModified();
        if (new_last_modified.empty())
            throw "No MAX(modified) found";

        for (auto &row : CheckError(db.GetModifiedServerCertificatesMeta(last_modified.c_str())))
            printf("%s %s %s\n",
                   row.GetValue(1),
                   *row.GetValue(0) == 't' ? "deleted" : "modified",
                   row.GetValue(2));

        last_modified = std::move(new_last_modified);
    }

    return EXIT_SUCCESS;
}

static int
Tail()
{
    CertDatabase db(config);

    for (auto &row : CheckError(db.TailModifiedServerCertificatesMeta()))
        printf("%s %s %s\n",
               row.GetValue(1),
               *row.GetValue(0) == 't' ? "deleted" : "modified",
               row.GetValue(2));

    return EXIT_SUCCESS;
}

int
main(int argc, char **argv)
{
    ConstBuffer<const char *> args(argv + 1, argc - 1);

    if (args.IsEmpty()) {
        fprintf(stderr, "Usage: %s COMMAND ...\n"
                "\n"
                "Commands:\n"
                "  load CERT KEY\n"
                "  delete HOST\n"
                "  find HOST\n"
                "  monitor\n"
                "  tail\n"
                "\n", argv[0]);
        return EXIT_FAILURE;
    }

    const auto cmd = args.shift();

    try {
        if (strcmp(cmd, "load") == 0) {
            if (args.size != 2) {
                fprintf(stderr, "Usage: %s load CERT KEY\n", argv[0]);
                return EXIT_FAILURE;
            }

            return LoadCertificate(args[0], args[1]);
        } else if (strcmp(cmd, "delete") == 0) {
            if (args.size != 1) {
                fprintf(stderr, "Usage: %s delete HOST\n", argv[0]);
                return EXIT_FAILURE;
            }

            return DeleteCertificate(args[0]);
        } else if (strcmp(cmd, "find") == 0) {
            if (args.size != 1) {
                fprintf(stderr, "Usage: %s find HOST\n", argv[0]);
                return EXIT_FAILURE;
            }

            return FindCertificate(args[0]);
        } else if (strcmp(cmd, "monitor") == 0) {
            if (args.size != 0) {
                fprintf(stderr, "Usage: %s monitor\n", argv[0]);
                return EXIT_FAILURE;
            }

            return Monitor();
        } else if (strcmp(cmd, "tail") == 0) {
            if (args.size != 0) {
                fprintf(stderr, "Usage: %s tail\n", argv[0]);
                return EXIT_FAILURE;
            }

            return Tail();
        } else {
            fprintf(stderr, "Unknown command: %s\n", cmd);
            return EXIT_FAILURE;
        }
    } catch (const std::exception &e) {
        fprintf(stderr, "%s\n", e.what());
        return EXIT_FAILURE;
    } catch (const char *msg) {
        fprintf(stderr, "%s\n", msg);
        return EXIT_FAILURE;
    }
}
<commit_msg>certdb/Main: send NOTIFY after delete<commit_after>#include "Config.hxx"
#include "CertDatabase.hxx"
#include "Wildcard.hxx"
#include "ssl/Util.hxx"
#include "ssl/Name.hxx"
#include "ssl/MemBio.hxx"
#include "ssl/Unique.hxx"
#include "pg/Error.hxx"
#include "util/ConstBuffer.hxx"

#include <inline/compiler.h>

#include <openssl/ts.h>

#include <stdexcept>

#include <stdio.h>
#include <stdlib.h>
#include <poll.h>

static const CertDatabaseConfig config{"dbname=lb", std::string()};

static PgResult
CheckError(PgResult &&result)
{
    if (result.IsError())
        throw PgError(std::move(result));

    return std::move(result);
}

gcc_pure
static AllocatedString<>
GetCommonName(X509_NAME &name)
{
    return NidToString(name, NID_commonName);
}

gcc_pure
static AllocatedString<>
GetCommonName(X509 *cert)
{
    X509_NAME *subject = X509_get_subject_name(cert);
    return subject != nullptr
        ? GetCommonName(*subject)
        : nullptr;
}

gcc_pure
static AllocatedString<>
FormatTime(ASN1_TIME *t)
{
    if (t == nullptr)
        return nullptr;

    return BioWriterToString([t](BIO &bio){
            ASN1_TIME_print(&bio, t);
        });
}

static int
LoadCertificate(const char *cert_path, const char *key_path)
{
    X509 *cert = TS_CONF_load_cert(cert_path);
    if (cert == nullptr) {
        fprintf(stderr, "Failed to load certificate\n");
        return EXIT_FAILURE;
    }

    const auto common_name = GetCommonName(cert);
    if (common_name == nullptr) {
        fprintf(stderr, "Certificate has no common name\n");
        return EXIT_FAILURE;
    }

    auto key = TS_CONF_load_key(key_path, nullptr);
    if (key == nullptr) {
        fprintf(stderr, "Failed to load key\n");
        return EXIT_FAILURE;
    }

    if (!MatchModulus(*cert, *key)) {
        fprintf(stderr, "Key and certificate do not match.\n");
        return EXIT_FAILURE;
    }

    CertDatabase db(config);

    unsigned char *cert_der_buffer = nullptr;
    int cert_der_length = i2d_X509(cert, &cert_der_buffer);
    if (cert_der_length < 0) {
        fprintf(stderr, "Failed to encode certificate\n");
        return EXIT_FAILURE;
    }

    const PgBinaryValue cert_der(cert_der_buffer, cert_der_length);

    unsigned char *key_der_buffer = nullptr;
    int key_der_length = i2d_PrivateKey(key, &key_der_buffer);
    if (key_der_length < 0) {
        fprintf(stderr, "Failed to encode key\n");
        return EXIT_FAILURE;
    }

    const PgBinaryValue key_der(key_der_buffer, key_der_length);

    const auto not_before = FormatTime(X509_get_notBefore(cert));
    if (not_before == nullptr) {
        fprintf(stderr, "Certificate does not have a notBefore time stamp\n");
        return EXIT_FAILURE;
    }

    const auto not_after = FormatTime(X509_get_notAfter(cert));
    if (not_after == nullptr) {
        fprintf(stderr, "Certificate does not have a notAfter time stamp\n");
        return EXIT_FAILURE;
    }

    auto result = CheckError(db.UpdateServerCertificate(common_name.c_str(),
                                                        not_before.c_str(),
                                                        not_after.c_str(),
                                                        cert_der, key_der));
    if (result.GetAffectedRows() > 0) {
        printf("update: %s\n", common_name.c_str());
    } else {
        CheckError(db.InsertServerCertificate(common_name.c_str(),
                                              not_before.c_str(),
                                              not_after.c_str(),
                                              cert_der, key_der));
        printf("insert: %s\n", common_name.c_str());
    }

    db.NotifyModified();

    return EXIT_SUCCESS;
}

static int
DeleteCertificate(const char *host)
{
    CertDatabase db(config);

    const auto result = CheckError(db.DeleteServerCertificateByCommonName(host));
    if (result.GetAffectedRows() == 0)
        throw "Certificate not found";

    db.NotifyModified();

    return EXIT_SUCCESS;
}

static UniqueX509
FindCertByCommonName(CertDatabase &db, const char *common_name)
{
    auto result = CheckError(db.FindServerCertificateByCommonName(common_name));
    if (result.GetRowCount() == 0)
        return nullptr;

    if (!result.IsColumnBinary(0) || result.IsValueNull(0, 0))
        throw "Unexpected result";

    auto cert_der = result.GetBinaryValue(0, 0);

    auto data = (const unsigned char *)cert_der.value;
    UniqueX509 cert(d2i_X509(nullptr, &data, cert_der.size));
    if (!cert)
        throw "d2i_X509() failed";

    return cert;
}

static UniqueX509
FindCertByHost(const char *host)
{
    CertDatabase db(config);

    auto cert = FindCertByCommonName(db, host);
    if (!cert) {
        auto wildcard = MakeCommonNameWildcard(host);
        if (!wildcard.empty())
            cert = FindCertByCommonName(db, wildcard.c_str());

        if (!cert)
            throw "Certificate not found";
    }

    return cert;
}

static int
FindCertificate(const char *host)
{
    auto cert = FindCertByHost(host);
    X509_print_fp(stdout, cert.get());
    PEM_write_X509(stdout, cert.get());
    return EXIT_SUCCESS;
}

static int
Monitor()
{
    CertDatabase db(config);
    CheckError(db.ListenModified());

    std::string last_modified = db.GetLastModified();
    if (last_modified.empty()) {
        last_modified = db.GetCurrentTimestamp();
        if (last_modified.empty())
            throw "CURRENT_TIMESTAMP failed";
    }

    struct pollfd pfd = {
        .fd = db.GetSocket(),
        .events = POLLIN,
    };

    while (true) {
        if (poll(&pfd, 1, -1) < 0)
            throw "poll() failed";

        db.ConsumeInput();
        while (db.GetNextNotify()) {}

        std::string new_last_modified = db.GetLastModified();
        if (new_last_modified.empty())
            throw "No MAX(modified) found";

        for (auto &row : CheckError(db.GetModifiedServerCertificatesMeta(last_modified.c_str())))
            printf("%s %s %s\n",
                   row.GetValue(1),
                   *row.GetValue(0) == 't' ? "deleted" : "modified",
                   row.GetValue(2));

        last_modified = std::move(new_last_modified);
    }

    return EXIT_SUCCESS;
}

static int
Tail()
{
    CertDatabase db(config);

    for (auto &row : CheckError(db.TailModifiedServerCertificatesMeta()))
        printf("%s %s %s\n",
               row.GetValue(1),
               *row.GetValue(0) == 't' ? "deleted" : "modified",
               row.GetValue(2));

    return EXIT_SUCCESS;
}

int
main(int argc, char **argv)
{
    ConstBuffer<const char *> args(argv + 1, argc - 1);

    if (args.IsEmpty()) {
        fprintf(stderr, "Usage: %s COMMAND ...\n"
                "\n"
                "Commands:\n"
                "  load CERT KEY\n"
                "  delete HOST\n"
                "  find HOST\n"
                "  monitor\n"
                "  tail\n"
                "\n", argv[0]);
        return EXIT_FAILURE;
    }

    const auto cmd = args.shift();

    try {
        if (strcmp(cmd, "load") == 0) {
            if (args.size != 2) {
                fprintf(stderr, "Usage: %s load CERT KEY\n", argv[0]);
                return EXIT_FAILURE;
            }

            return LoadCertificate(args[0], args[1]);
        } else if (strcmp(cmd, "delete") == 0) {
            if (args.size != 1) {
                fprintf(stderr, "Usage: %s delete HOST\n", argv[0]);
                return EXIT_FAILURE;
            }

            return DeleteCertificate(args[0]);
        } else if (strcmp(cmd, "find") == 0) {
            if (args.size != 1) {
                fprintf(stderr, "Usage: %s find HOST\n", argv[0]);
                return EXIT_FAILURE;
            }

            return FindCertificate(args[0]);
        } else if (strcmp(cmd, "monitor") == 0) {
            if (args.size != 0) {
                fprintf(stderr, "Usage: %s monitor\n", argv[0]);
                return EXIT_FAILURE;
            }

            return Monitor();
        } else if (strcmp(cmd, "tail") == 0) {
            if (args.size != 0) {
                fprintf(stderr, "Usage: %s tail\n", argv[0]);
                return EXIT_FAILURE;
            }

            return Tail();
        } else {
            fprintf(stderr, "Unknown command: %s\n", cmd);
            return EXIT_FAILURE;
        }
    } catch (const std::exception &e) {
        fprintf(stderr, "%s\n", e.what());
        return EXIT_FAILURE;
    } catch (const char *msg) {
        fprintf(stderr, "%s\n", msg);
        return EXIT_FAILURE;
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2010 Satoshi Nakamoto
// Copyright (c) 2009-2014 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "chainparams.h"

#include "assert.h"
#include "core.h"
#include "protocol.h"
#include "util.h"

#include <boost/assign/list_of.hpp>

using namespace boost::assign;

//
// Main network
//

unsigned int pnSeed[] =
{
    0x12345678
};

class CMainParams : public CChainParams {
public:
    CMainParams() {
        // The message start string is designed to be unlikely to occur in normal data.
        // The characters are rarely used upper ASCII, not valid as UTF-8, and produce
        // a large 4-byte int at any alignment.
        pchMessageStart[0] = 0x05;
        pchMessageStart[1] = 0x05;
        pchMessageStart[2] = 0xb5;
        pchMessageStart[3] = 0x05;
        nDefaultPort = 5530;
        nRPCPort = 5531;
        // vAlertPubKey = ParseHex("");
        bnProofOfWorkLimit = CBigNum(~uint256(0) >> 20);
        nSubsidyHalvingInterval = 100000;

        // Build the genesis block. Note that the output of the genesis coinbase cannot
        // be spent as it did not originally exist in the database.
        const char* pszTimestamp = "vcoin sn";
        CTransaction txNew;
        txNew.vin.resize(1);
        txNew.vout.resize(1);
        txNew.vin[0].scriptSig = CScript() << 486604799 << CBigNum(4) << vector<unsigned char>((const unsigned char*)pszTimestamp, (const unsigned char*)pszTimestamp + strlen(pszTimestamp));
        txNew.vout[0].nValue = 1 * COIN;
        txNew.vout[0].scriptPubKey = CScript() << ParseHex("") << OP_CHECKSIG;
        genesis.vtx.push_back(txNew);
        genesis.hashPrevBlock = 0;
        genesis.hashMerkleRoot = genesis.BuildMerkleTree();
        genesis.nVersion = 1;
        genesis.nTime    = 1431517588;
        genesis.nBits    = 0x1e0fffff;
        genesis.nNonce   = 1486592;
        hashGenesisBlock = genesis.GetHash();
        /*
        //// debug print
        while (hashGenesisBlock > bnProofOfWorkLimit.getuint256()){
            if (++genesis.nNonce==0) break;
            hashGenesisBlock = genesis.GetHash();
        }

        printf("mainnet: %s\n", hashGenesisBlock.ToString().c_str());
        printf("mainnet: %s\n", genesis.hashMerkleRoot.ToString().c_str());
        printf("mainnet: %x\n", bnProofOfWorkLimit.GetCompact());
        genesis.print();

        */

        assert(hashGenesisBlock == uint256("0x00000b7e804f0de87e7752550ff04d7686a4599509897feefd7f03904eb45633"));
        assert(genesis.hashMerkleRoot == uint256("0x1576ef41775095b26a8f8f2bb65b693ec12230608a425aa84ee462381cae00e6"));

        vSeeds.push_back(CDNSSeedData("someaddress.com or IP addy", "someaddress.com"));

        base58Prefixes[PUBKEY_ADDRESS] = list_of(70);
        base58Prefixes[SCRIPT_ADDRESS] = list_of(30);
        base58Prefixes[SECRET_KEY]     = list_of(224);
        base58Prefixes[EXT_PUBLIC_KEY] = list_of(0x04)(0x88)(0xB2)(0x1E);
        base58Prefixes[EXT_SECRET_KEY] = list_of(0x04)(0x88)(0xAD)(0xE4);

        // Convert the pnSeeds array into usable address objects.
        for (unsigned int i = 0; i < ARRAYLEN(pnSeed); i++)
        {
            // It'll only connect to one or two seed nodes because once it connects,
            // it'll get a pile of addresses with newer timestamps.
            // Seed nodes are given a random 'last seen time' of between one and two
            // weeks ago.
            const int64_t nOneWeek = 7*24*60*60;
            struct in_addr ip;
            memcpy(&ip, &pnSeed[i], sizeof(ip));
            CAddress addr(CService(ip, GetDefaultPort()));
            addr.nTime = GetTime() - GetRand(nOneWeek) - nOneWeek;
            vFixedSeeds.push_back(addr);
        }
    }

    virtual const CBlock& GenesisBlock() const { return genesis; }
    virtual Network NetworkID() const { return CChainParams::MAIN; }

    virtual const vector<CAddress>& FixedSeeds() const {
        return vFixedSeeds;
    }
protected:
    CBlock genesis;
    vector<CAddress> vFixedSeeds;
};
static CMainParams mainParams;

//
// Testnet (v3)
//
class CTestNetParams : public CMainParams {
public:
    CTestNetParams() {
        // The message start string is designed to be unlikely to occur in normal data.
        // The characters are rarely used upper ASCII, not valid as UTF-8, and produce
        // a large 4-byte int at any alignment.
        pchMessageStart[0] = 0x01;
        pchMessageStart[1] = 0xfe;
        pchMessageStart[2] = 0xfe;
        pchMessageStart[3] = 0x05;
        vAlertPubKey = ParseHex("");
        nDefaultPort = 55534;
        nRPCPort = 55535;
        bnProofOfWorkLimit = CBigNum(~uint256(0) >> 20);
        strDataDir = "testnet3";

        // Modify the testnet genesis block so the timestamp is valid for a later start.
        genesis.nTime = 1374901774;
        genesis.nBits = bnProofOfWorkLimit.GetCompact();
        genesis.nNonce = 243324;

        //// debug print
        hashGenesisBlock = genesis.GetHash();
        /*
        //while (hashGenesisBlock > bnProofOfWorkLimit.getuint256()){
        //    if (++genesis.nNonce==0) break;
        //   hashGenesisBlock = genesis.GetHash();
        //}

        printf("testnet: %s\n", hashGenesisBlock.ToString().c_str());
        printf("testnet: %s\n", genesis.hashMerkleRoot.ToString().c_str());
        printf("testnet: %x\n", bnProofOfWorkLimit.GetCompact());
        genesis.print();

        */

        assert(hashGenesisBlock == uint256("0x0000031225834a1423f72fc7f8371e46b0ed172da9a9242edb891902abb85759"));

        vFixedSeeds.clear();
        vSeeds.clear();
        // vSeeds.push_back(CDNSSeedData("vcoin.test", "test.vcoin.org"));

        base58Prefixes[PUBKEY_ADDRESS] = list_of(130);
        base58Prefixes[SCRIPT_ADDRESS] = list_of(30);
        base58Prefixes[SECRET_KEY]     = list_of(239);
        base58Prefixes[EXT_PUBLIC_KEY] = list_of(0x04)(0x35)(0x87)(0xCF);
        base58Prefixes[EXT_SECRET_KEY] = list_of(0x04)(0x35)(0x83)(0x94);
    }
    virtual Network NetworkID() const { return CChainParams::TESTNET; }
};
static CTestNetParams testNetParams;

//
// Regression test
//
class CRegTestParams : public CTestNetParams {
public:
    CRegTestParams() {
        pchMessageStart[0] = 0xfa;
        pchMessageStart[1] = 0x0f;
        pchMessageStart[2] = 0xa5;
        pchMessageStart[3] = 0x5a;
        nSubsidyHalvingInterval = 150;
        bnProofOfWorkLimit = CBigNum(~uint256(0) >> 1);
        genesis.nTime = 1296688602;
        genesis.nBits = 0x207fffff;
        genesis.nNonce = 3;
        hashGenesisBlock = genesis.GetHash();
        nDefaultPort = 18444;
        strDataDir = "regtest";

        //// debug print
        hashGenesisBlock = genesis.GetHash();
        /*
        //while (hashGenesisBlock > bnProofOfWorkLimit.getuint256()){
        //    if (++genesis.nNonce==0) break;
        //    hashGenesisBlock = genesis.GetHash();
        //}

        printf("regtest: %s\n", hashGenesisBlock.ToString().c_str());
        printf("regtest: %s\n", genesis.hashMerkleRoot.ToString().c_str());
        printf("regtest: %x\n", bnProofOfWorkLimit.GetCompact());
        genesis.print();

        */

        // assert(hashGenesisBlock == uint256(""));

        vSeeds.clear();  // Regtest mode doesn't have any DNS seeds.

        base58Prefixes[PUBKEY_ADDRESS] = list_of(0);
        base58Prefixes[SCRIPT_ADDRESS] = list_of(5);
        base58Prefixes[SECRET_KEY]     = list_of(128);
        base58Prefixes[EXT_PUBLIC_KEY] = list_of(0x04)(0x35)(0x87)(0xCF);
        base58Prefixes[EXT_SECRET_KEY] = list_of(0x04)(0x35)(0x83)(0x94);
    }

    virtual bool RequireRPCPassword() const { return false; }
    virtual Network NetworkID() const { return CChainParams::REGTEST; }
};
static CRegTestParams regTestParams;

static CChainParams *pCurrentParams = &mainParams;

const CChainParams &Params() {
    return *pCurrentParams;
}

void SelectParams(CChainParams::Network network) {
    switch (network) {
        case CChainParams::MAIN:
            pCurrentParams = &mainParams;
            break;
        case CChainParams::TESTNET:
            pCurrentParams = &testNetParams;
            break;
        case CChainParams::REGTEST:
            pCurrentParams = &regTestParams;
            break;
        default:
            assert(false && "Unimplemented network");
            return;
    }
}

bool SelectParamsFromCommandLine() {
    bool fRegTest = GetBoolArg("-regtest", false);
    bool fTestNet = GetBoolArg("-testnet", false);

    if (fTestNet && fRegTest) {
        return false;
    }

    if (fRegTest) {
        SelectParams(CChainParams::REGTEST);
    } else if (fTestNet) {
        SelectParams(CChainParams::TESTNET);
    } else {
        SelectParams(CChainParams::MAIN);
    }
    return true;
}
<commit_msg>add boost lib switch<commit_after>// Copyright (c) 2010 Satoshi Nakamoto
// Copyright (c) 2009-2014 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "chainparams.h"

#include "assert.h"
#include "core.h"
#include "protocol.h"
#include "util.h"

#include <boost/assign/list_of.hpp>

using namespace boost::assign;

//
// Main network
//

unsigned int pnSeed[] =
{
    0x12345678
};

class CMainParams : public CChainParams {
public:
    CMainParams() {
        // The message start string is designed to be unlikely to occur in normal data.
        // The characters are rarely used upper ASCII, not valid as UTF-8, and produce
        // a large 4-byte int at any alignment.
        pchMessageStart[0] = 0x05;
        pchMessageStart[1] = 0x05;
        pchMessageStart[2] = 0xb5;
        pchMessageStart[3] = 0x05;
        nDefaultPort = 5530;
        nRPCPort = 5531;
        // vAlertPubKey = ParseHex("");
        bnProofOfWorkLimit = CBigNum(~uint256(0) >> 20);
        nSubsidyHalvingInterval = 100000;

        // Build the genesis block. Note that the output of the genesis coinbase cannot
        // be spent as it did not originally exist in the database.
        const char* pszTimestamp = "vcoin sn";
        CTransaction txNew;
        txNew.vin.resize(1);
        txNew.vout.resize(1);
        txNew.vin[0].scriptSig = CScript() << 486604799 << CBigNum(4) << vector<unsigned char>((const unsigned char*)pszTimestamp, (const unsigned char*)pszTimestamp + strlen(pszTimestamp));
        txNew.vout[0].nValue = 1 * COIN;
        txNew.vout[0].scriptPubKey = CScript() << ParseHex("") << OP_CHECKSIG;
        genesis.vtx.push_back(txNew);
        genesis.hashPrevBlock = 0;
        genesis.hashMerkleRoot = genesis.BuildMerkleTree();
        genesis.nVersion = 1;
        genesis.nTime    = 1431517588;
        genesis.nBits    = 0x1e0fffff;
        genesis.nNonce   = 1486592;
        hashGenesisBlock = genesis.GetHash();
        /*
        //// debug print
        while (hashGenesisBlock > bnProofOfWorkLimit.getuint256()){
            if (++genesis.nNonce==0) break;
            hashGenesisBlock = genesis.GetHash();
        }

        printf("mainnet: %s\n", hashGenesisBlock.ToString().c_str());
        printf("mainnet: %s\n", genesis.hashMerkleRoot.ToString().c_str());
        printf("mainnet: %x\n", bnProofOfWorkLimit.GetCompact());
        genesis.print();

        */

        assert(hashGenesisBlock == uint256("0x00000b7e804f0de87e7752550ff04d7686a4599509897feefd7f03904eb45633"));
        assert(genesis.hashMerkleRoot == uint256("0x1576ef41775095b26a8f8f2bb65b693ec12230608a425aa84ee462381cae00e6"));

        vSeeds.push_back(CDNSSeedData("someaddress.com or IP addy", "someaddress.com"));

#if BOOST_VERSION >= 106000
        base58Prefixes[PUBKEY_ADDRESS] = std::vector<unsigned char>(1,70);                    // VCoin addresses start with 'V'
        base58Prefixes[SCRIPT_ADDRESS] = std::vector<unsigned char>(1,30);                    // VCoin script addresses start with '7'
        base58Prefixes[SECRET_KEY] =     std::vector<unsigned char>(1,96 + 128);              // VCoin private keys start with '7' or 'V'
        base58Prefixes[EXT_PUBLIC_KEY] = boost::assign::list_of(0x04)(0x88)(0xB2)(0x1E).convert_to_container<std::vector<unsigned char> >(); // Chaincoin BIP32 pubkeys start with 'drkv'
        base58Prefixes[EXT_SECRET_KEY] = boost::assign::list_of(0x04)(0x88)(0xAD)(0xE4).convert_to_container<std::vector<unsigned char> >(); // Chaincoin BIP32 prvkeys start with 'drkp'
#else
        base58Prefixes[PUBKEY_ADDRESS] = list_of(70);
        base58Prefixes[SCRIPT_ADDRESS] = list_of(30);
        base58Prefixes[SECRET_KEY]     = list_of(224);
        base58Prefixes[EXT_PUBLIC_KEY] = list_of(0x04)(0x88)(0xB2)(0x1E);
        base58Prefixes[EXT_SECRET_KEY] = list_of(0x04)(0x88)(0xAD)(0xE4);
#endif
        // Convert the pnSeeds array into usable address objects.
        for (unsigned int i = 0; i < ARRAYLEN(pnSeed); i++)
        {
            // It'll only connect to one or two seed nodes because once it connects,
            // it'll get a pile of addresses with newer timestamps.
            // Seed nodes are given a random 'last seen time' of between one and two
            // weeks ago.
            const int64_t nOneWeek = 7*24*60*60;
            struct in_addr ip;
            memcpy(&ip, &pnSeed[i], sizeof(ip));
            CAddress addr(CService(ip, GetDefaultPort()));
            addr.nTime = GetTime() - GetRand(nOneWeek) - nOneWeek;
            vFixedSeeds.push_back(addr);
        }
    }

    virtual const CBlock& GenesisBlock() const { return genesis; }
    virtual Network NetworkID() const { return CChainParams::MAIN; }

    virtual const vector<CAddress>& FixedSeeds() const {
        return vFixedSeeds;
    }
protected:
    CBlock genesis;
    vector<CAddress> vFixedSeeds;
};
static CMainParams mainParams;

//
// Testnet (v3)
//
class CTestNetParams : public CMainParams {
public:
    CTestNetParams() {
        // The message start string is designed to be unlikely to occur in normal data.
        // The characters are rarely used upper ASCII, not valid as UTF-8, and produce
        // a large 4-byte int at any alignment.
        pchMessageStart[0] = 0x01;
        pchMessageStart[1] = 0xfe;
        pchMessageStart[2] = 0xfe;
        pchMessageStart[3] = 0x05;
        vAlertPubKey = ParseHex("");
        nDefaultPort = 55534;
        nRPCPort = 55535;
        bnProofOfWorkLimit = CBigNum(~uint256(0) >> 20);
        strDataDir = "testnet3";

        // Modify the testnet genesis block so the timestamp is valid for a later start.
        genesis.nTime = 1374901774;
        genesis.nBits = bnProofOfWorkLimit.GetCompact();
        genesis.nNonce = 243324;

        //// debug print
        hashGenesisBlock = genesis.GetHash();
        /*
        //while (hashGenesisBlock > bnProofOfWorkLimit.getuint256()){
        //    if (++genesis.nNonce==0) break;
        //   hashGenesisBlock = genesis.GetHash();
        //}

        printf("testnet: %s\n", hashGenesisBlock.ToString().c_str());
        printf("testnet: %s\n", genesis.hashMerkleRoot.ToString().c_str());
        printf("testnet: %x\n", bnProofOfWorkLimit.GetCompact());
        genesis.print();

        */

        assert(hashGenesisBlock == uint256("0x0000031225834a1423f72fc7f8371e46b0ed172da9a9242edb891902abb85759"));

        vFixedSeeds.clear();
        vSeeds.clear();
        // vSeeds.push_back(CDNSSeedData("vcoin.test", "test.vcoin.org"));

#if BOOST_VERSION >= 106000
        base58Prefixes[PUBKEY_ADDRESS] = std::vector<unsigned char>(1,130);                    // VCoin addresses start with 'V'
        base58Prefixes[SCRIPT_ADDRESS] = std::vector<unsigned char>(1,30);                    // VCoin script addresses start with '7'
        base58Prefixes[SECRET_KEY] =     std::vector<unsigned char>(1,111 + 128);              // VCoin private keys start with '7' or 'V'
        base58Prefixes[EXT_PUBLIC_KEY] = boost::assign::list_of(0x04)(0x35)(0x87)(0xCF).convert_to_container<std::vector<unsigned char> >(); // Chaincoin BIP32 pubkeys start with 'drkv'
        base58Prefixes[EXT_SECRET_KEY] = boost::assign::list_of(0x04)(0x35)(0x83)(0x94).convert_to_container<std::vector<unsigned char> >(); // Chaincoin BIP32 prvkeys start with 'drkp'
#else
        base58Prefixes[PUBKEY_ADDRESS] = list_of(130);
        base58Prefixes[SCRIPT_ADDRESS] = list_of(30);
        base58Prefixes[SECRET_KEY]     = list_of(239);
        base58Prefixes[EXT_PUBLIC_KEY] = list_of(0x04)(0x35)(0x87)(0xCF);
        base58Prefixes[EXT_SECRET_KEY] = list_of(0x04)(0x35)(0x83)(0x94);
#endif
    }
    virtual Network NetworkID() const { return CChainParams::TESTNET; }
};
static CTestNetParams testNetParams;

//
// Regression test
//
class CRegTestParams : public CTestNetParams {
public:
    CRegTestParams() {
        pchMessageStart[0] = 0xfa;
        pchMessageStart[1] = 0x0f;
        pchMessageStart[2] = 0xa5;
        pchMessageStart[3] = 0x5a;
        nSubsidyHalvingInterval = 150;
        bnProofOfWorkLimit = CBigNum(~uint256(0) >> 1);
        genesis.nTime = 1296688602;
        genesis.nBits = 0x207fffff;
        genesis.nNonce = 3;
        hashGenesisBlock = genesis.GetHash();
        nDefaultPort = 18444;
        strDataDir = "regtest";

        //// debug print
        hashGenesisBlock = genesis.GetHash();
        /*
        //while (hashGenesisBlock > bnProofOfWorkLimit.getuint256()){
        //    if (++genesis.nNonce==0) break;
        //    hashGenesisBlock = genesis.GetHash();
        //}

        printf("regtest: %s\n", hashGenesisBlock.ToString().c_str());
        printf("regtest: %s\n", genesis.hashMerkleRoot.ToString().c_str());
        printf("regtest: %x\n", bnProofOfWorkLimit.GetCompact());
        genesis.print();

        */

        // assert(hashGenesisBlock == uint256(""));

        vSeeds.clear();  // Regtest mode doesn't have any DNS seeds.

#if BOOST_VERSION >= 106000
        base58Prefixes[PUBKEY_ADDRESS] = std::vector<unsigned char>(1,0);                    // VCoin addresses start with 'V'
        base58Prefixes[SCRIPT_ADDRESS] = std::vector<unsigned char>(1,5);                    // VCoin script addresses start with '7'
        base58Prefixes[SECRET_KEY] =     std::vector<unsigned char>(1,128);              // VCoin private keys start with '7' or 'V'
        base58Prefixes[EXT_PUBLIC_KEY] = boost::assign::list_of(0x04)(0x35)(0x87)(0xCF).convert_to_container<std::vector<unsigned char> >(); // Chaincoin BIP32 pubkeys start with 'drkv'
        base58Prefixes[EXT_SECRET_KEY] = boost::assign::list_of(0x04)(0x35)(0x83)(0x94).convert_to_container<std::vector<unsigned char> >(); // Chaincoin BIP32 prvkeys start with 'drkp'
#else
        base58Prefixes[PUBKEY_ADDRESS] = list_of(0);
        base58Prefixes[SCRIPT_ADDRESS] = list_of(5);
        base58Prefixes[SECRET_KEY]     = list_of(128);
        base58Prefixes[EXT_PUBLIC_KEY] = list_of(0x04)(0x35)(0x87)(0xCF);
        base58Prefixes[EXT_SECRET_KEY] = list_of(0x04)(0x35)(0x83)(0x94);
#endif
    }

    virtual bool RequireRPCPassword() const { return false; }
    virtual Network NetworkID() const { return CChainParams::REGTEST; }
};
static CRegTestParams regTestParams;

static CChainParams *pCurrentParams = &mainParams;

const CChainParams &Params() {
    return *pCurrentParams;
}

void SelectParams(CChainParams::Network network) {
    switch (network) {
        case CChainParams::MAIN:
            pCurrentParams = &mainParams;
            break;
        case CChainParams::TESTNET:
            pCurrentParams = &testNetParams;
            break;
        case CChainParams::REGTEST:
            pCurrentParams = &regTestParams;
            break;
        default:
            assert(false && "Unimplemented network");
            return;
    }
}

bool SelectParamsFromCommandLine() {
    bool fRegTest = GetBoolArg("-regtest", false);
    bool fTestNet = GetBoolArg("-testnet", false);

    if (fTestNet && fRegTest) {
        return false;
    }

    if (fRegTest) {
        SelectParams(CChainParams::REGTEST);
    } else if (fTestNet) {
        SelectParams(CChainParams::TESTNET);
    } else {
        SelectParams(CChainParams::MAIN);
    }
    return true;
}
<|endoftext|>


<commit_before>#include "any.hpp"

#include "dyn_lib.hpp"

#include <gtest/gtest.h>

struct A
{
    explicit A(int i) :
        m_i(i) {}
    int m_i;
};

TEST(any, readme_example)
{
    static_any<32> a; // on g++ 5.x sizeof(std::string) is 32
    static_assert(sizeof(a) == 32 + sizeof(std::ptrdiff_t), "impossible");

    a = 1234;
    ASSERT_EQ(1234, a.get<int>());

    a = std::string("Hello world");
    ASSERT_EQ(std::string("Hello world"), a.get<std::string>());

    struct A
    {
        explicit A(long i = 0, double d = .0)
         : i_(i), d_(d) {}

        long i_;
        double d_;
    };

    a = A(12, .34);
}

TEST(any, test_sizeof)
{
    static_any<16> a;
    ASSERT_EQ(16 + sizeof(std::ptrdiff_t), sizeof(a));
}

TEST(any, capacity)
{
    static_any<32> a;
    ASSERT_EQ(32, a.capacity());

    a = std::string("hello world");
    ASSERT_EQ(32, a.capacity());

    a.reset();
    ASSERT_EQ(32, a.capacity());
}

TEST(any, size)
{
    static_any<32> a;
    ASSERT_EQ(0, a.size());

    a = 1234;
    ASSERT_EQ(sizeof(1234), a.size());

    a = std::string("foobar");
    ASSERT_EQ(sizeof(std::string), a.size());

    a.reset();
    ASSERT_EQ(0, a.size());
}

struct CallCounter
{
    CallCounter() { default_constructions++; }
    CallCounter(const CallCounter&) { copy_constructions++; }
    CallCounter(CallCounter&&) { move_constructions++; }
    ~CallCounter() { destructions++; }

    static void reset_counters()
    {
        default_constructions = 0;
        copy_constructions = 0;
        move_constructions = 0;
        destructions = 0;
    }

    static int default_constructions;
    static int copy_constructions;
    static int move_constructions;
    static int destructions;
};

int CallCounter::default_constructions = 0;
int CallCounter::copy_constructions = 0;
int CallCounter::move_constructions = 0;
int CallCounter::destructions = 0;

TEST(any, default_constructed_is_empty)
{
    static_any<16> a;
    ASSERT_TRUE(a.empty());
}

TEST(any, contructed_with_param_non_empty)
{
    static_any<16> a(77); // will contain integer
    ASSERT_FALSE(a.empty());
}

TEST(any, has)
{
    static_any<16> a(77); // will contain integer
    ASSERT_TRUE(a.has<int>());
    ASSERT_FALSE(a.has<double>());
}

TEST(any, move_construct)
{
    CallCounter::reset_counters();
    CallCounter counter;
    static_any<16> a(std::move(counter));

    ASSERT_EQ(1, CallCounter::default_constructions);
    ASSERT_EQ(0, CallCounter::copy_constructions);
    ASSERT_EQ(1, CallCounter::move_constructions);
    ASSERT_EQ(0, CallCounter::destructions);
}

TEST(any, copy_construct)
{
    CallCounter::reset_counters();
    CallCounter counter;
    static_any<16> a(counter);

    ASSERT_EQ(1, CallCounter::default_constructions);
    ASSERT_EQ(1, CallCounter::copy_constructions);
    ASSERT_EQ(0, CallCounter::move_constructions);
    ASSERT_EQ(0, CallCounter::destructions);
}

TEST(any, destruction)
{
    CallCounter::reset_counters();
    CallCounter counter;
    {
        static_any<16> a(counter);
    }

    ASSERT_EQ(1, CallCounter::destructions);
}

TEST(any, reset_destruction)
{
    CallCounter::reset_counters();
    CallCounter counter;

    static_any<16> a(counter);
    a.reset();

    ASSERT_EQ(1, CallCounter::destructions);
}

TEST(any, copy_assignment)
{
    CallCounter::reset_counters();
    CallCounter counter;

    static_any<16> a(1);
    a = counter;

    ASSERT_EQ(1, CallCounter::default_constructions);
    ASSERT_EQ(1, CallCounter::copy_constructions);
    ASSERT_EQ(0, CallCounter::move_constructions);
}

TEST(any, move_assignment)
{
    CallCounter::reset_counters();
    CallCounter counter;

    static_any<16> a;
    a = std::move(counter);

    ASSERT_EQ(1, CallCounter::default_constructions);
    ASSERT_EQ(0, CallCounter::copy_constructions);
    ASSERT_EQ(1, CallCounter::move_constructions);
}

TEST(any, reassignment)
{
    CallCounter::reset_counters();
    CallCounter counter;

    static_any<16> a(counter);
    a = counter;

    ASSERT_EQ(1, CallCounter::default_constructions);
    ASSERT_EQ(2, CallCounter::copy_constructions);
    ASSERT_EQ(0, CallCounter::move_constructions);
    ASSERT_EQ(1, CallCounter::destructions);
}

TEST(any, not_empty_after_assignment)
{
    static_any<16> a;
    ASSERT_TRUE(a.empty());
    a = 7;
    ASSERT_FALSE(a.empty());
}

TEST(any, different_type_after_assignment)
{
    static_any<16> a(7);
    ASSERT_TRUE(a.has<int>());
    ASSERT_FALSE(a.has<double>());
    a = 3.14;
    ASSERT_FALSE(a.has<int>());
    ASSERT_TRUE(a.has<double>());
}

TEST(any, get_good_type)
{
    static_any<16> a(7);
    auto i = a.get<int>();
    ASSERT_EQ(7, i);
}

TEST(any, get_bad_type)
{
    static_any<16> a(7);
    EXPECT_THROW(a.get<double>(), std::bad_cast);
}

TEST(any, get_empty)
{
    static_any<16> a;
    EXPECT_THROW(a.get<double>(), std::bad_cast);
}

TEST(any, cast_empty)
{
    static_any<16> a;
    EXPECT_THROW(any_cast<int>(a), std::bad_cast);
}

TEST(any, mutable_get)
{
    static_any<16> a(7);
    a.get<int>() = 6;
    const static_any<16>& const_ref = a;
    auto i = const_ref.get<int>();
    ASSERT_EQ(6, i);
}

TEST(any, any_to_any_copy_uninitialized)
{
    static_any<16> a;
    static_any<16> b(a);

    ASSERT_TRUE(a.empty());
    ASSERT_TRUE(b.empty());
}

TEST(any, any_to_any_copy_construction)
{
    static_any<16> a(7);
    static_any<16> b(a);

    ASSERT_EQ(7, a.get<int>());
    ASSERT_EQ(7, b.get<int>());
}

TEST(any, any_to_any_assignment)
{
    static_any<32> a(std::string("Hello"));
    static_any<32> b;

    ASSERT_TRUE(b.empty());
    b = a;
    ASSERT_FALSE(b.empty());

    ASSERT_EQ("Hello", b.get<std::string>());
    ASSERT_EQ("Hello", a.get<std::string>());
}

TEST(any, any_to_any_move_construction)
{
    static_any<32> a(std::string("Hello"));
    static_any<32> b = std::move(a);

    ASSERT_FALSE(a.empty());
    ASSERT_FALSE(b.empty());

    ASSERT_EQ("Hello", b.get<std::string>());
}

TEST(any, any_to_bigger_any)
{
    static_any<16> a(1);
    ASSERT_EQ(1, a.get<int>());

    static_any<32> b(2);
    b = a;

    ASSERT_EQ(1, b.get<int>());
}

TEST(any, any_to_bigger_any_copy)
{
    static_any<16> a(1);
    ASSERT_EQ(1, a.get<int>());

    static_any<32> b = a;
    ASSERT_EQ(1, b.get<int>());
}

struct InitCtor
{
    int x = 1;
    int y = 2;
    InitCtor() = default;
    InitCtor(int x, int y) : x(x), y(y) {}
};

TEST(any, emplace_no_params)
{
    static_any<32> a;
    a.emplace<InitCtor>();

    ASSERT_FALSE(a.empty());
    EXPECT_EQ(1, a.get<InitCtor>().x);
    EXPECT_EQ(2, a.get<InitCtor>().y);
}

TEST(any, emplace_params)
{
    static_any<32> a;
    a.emplace<InitCtor>(77, 88);

    ASSERT_FALSE(a.empty());
    EXPECT_EQ(77, a.get<InitCtor>().x);
    EXPECT_EQ(88, a.get<InitCtor>().y);
}

TEST(any, destroyed_after_emplace)
{
    CallCounter::reset_counters();
    {
        static_any<32> a;
        a.emplace<CallCounter>();
    }

    EXPECT_EQ(1, CallCounter::default_constructions);
    EXPECT_EQ(1, CallCounter::destructions);
}

TEST(any, any_cast_pointer_correct_type)
{
    static_any<16> a(7);
    ASSERT_EQ(7, *any_cast<int>(&a));
}

TEST(any, any_cast_pointer_constness)
{
    static_any<16> a(7);
    const auto* a2 = &a;

    auto* pv  = any_cast<int>(&a);
    auto* pv2 = any_cast<int>(a2);

    ASSERT_FALSE(std::is_const<std::remove_pointer<decltype(pv)>::type>::value);
    ASSERT_TRUE(std::is_const<std::remove_pointer<decltype(pv2)>::type>::value);

    ASSERT_EQ(7, *pv);
    ASSERT_EQ(7, *pv2);
}

TEST(any, any_cast_pointer_wrong_type)
{
    static_any<16> a(7);
    ASSERT_EQ(nullptr, any_cast<float>(&a));
}

TEST(any, any_cast_reference_correct_type)
{
    static_any<16> a(7);
    ASSERT_EQ(7, any_cast<int>(a));
}

TEST(any, any_cast_reference_constness)
{
    static_any<16> a(7);
    const auto& a2 = a;

    auto& pv = any_cast<int>(a);
    auto& pv2 = any_cast<int>(a2);

    ASSERT_FALSE(std::is_const<std::remove_reference<decltype(pv)>::type>::value);
    ASSERT_TRUE(std::is_const<std::remove_reference<decltype(pv2)>::type>::value);

    ASSERT_EQ(7, pv);
    ASSERT_EQ(7, pv2);
}

TEST(any, any_cast_reference_wrong_type)
{
    static_any<16> a(7);
    EXPECT_THROW(any_cast<float>(a), bad_any_cast);
}

TEST(any, any_cast_reference_wrong_type_from_to)
{
    static_any<16> a(7);

    try {
        auto f = any_cast<float>(a);
        FAIL();
        ASSERT_EQ(.1234, f); // to avoid a warning, never reached
    }
    catch(bad_any_cast& ex) {
        ASSERT_EQ(typeid(int), ex.stored_type());
        ASSERT_EQ(typeid(float), ex.target_type());
    }
}

TEST(any, query_type)
{
    static_any<32> a(7);
    ASSERT_EQ(typeid(int), a.type());

    a = std::string("f00");
    ASSERT_EQ(typeid(std::string), a.type());
}

TEST(any, reset_empty)
{
    static_any<16> a(7);
    ASSERT_FALSE(a.empty());
    a.reset();
    ASSERT_TRUE(a.empty());
}

TEST(any, reset_has)
{
    static_any<16> a(7);
    ASSERT_TRUE(a.has<int>());
    a.reset();
    ASSERT_FALSE(a.has<int>());
}

TEST(any, type_identification_across_dll)
{
    auto a = get_any_with_int(7);
    EXPECT_TRUE(a.has<int>());
    EXPECT_FALSE(a.has<std::string>());

    EXPECT_EQ(7, a.get<int>());

    EXPECT_THROW(a.get<std::string>(), bad_any_cast);
}

TEST(any_t, simple)
{
    static_any_t<16> a(7);
    ASSERT_EQ(7, a.get<int>());
}

struct unsafe_to_copy
{
    unsafe_to_copy() =default;
    unsafe_to_copy(const unsafe_to_copy&) { throw 123; }
};

TEST(any_exception, init)
{
    EXPECT_THROW(static_any<16> a = unsafe_to_copy(), int);
}

TEST(any_exception, move)
{
    static_any<16> a;

    EXPECT_THROW(a = unsafe_to_copy(), int);
    EXPECT_TRUE(a.empty());
}

TEST(any_exception, copy)
{
    static_any<16> a;
    unsafe_to_copy u;

    EXPECT_THROW(a = u, int);
    EXPECT_TRUE(a.empty());
}

<commit_msg>unit_tests: adding emplace exceptiontest<commit_after>#include "any.hpp"

#include "dyn_lib.hpp"

#include <gtest/gtest.h>

struct A
{
    explicit A(int i) :
        m_i(i) {}
    int m_i;
};

TEST(any, readme_example)
{
    static_any<32> a; // on g++ 5.x sizeof(std::string) is 32
    static_assert(sizeof(a) == 32 + sizeof(std::ptrdiff_t), "impossible");

    a = 1234;
    ASSERT_EQ(1234, a.get<int>());

    a = std::string("Hello world");
    ASSERT_EQ(std::string("Hello world"), a.get<std::string>());

    struct A
    {
        explicit A(long i = 0, double d = .0)
         : i_(i), d_(d) {}

        long i_;
        double d_;
    };

    a = A(12, .34);
}

TEST(any, test_sizeof)
{
    static_any<16> a;
    ASSERT_EQ(16 + sizeof(std::ptrdiff_t), sizeof(a));
}

TEST(any, capacity)
{
    static_any<32> a;
    ASSERT_EQ(32, a.capacity());

    a = std::string("hello world");
    ASSERT_EQ(32, a.capacity());

    a.reset();
    ASSERT_EQ(32, a.capacity());
}

TEST(any, size)
{
    static_any<32> a;
    ASSERT_EQ(0, a.size());

    a = 1234;
    ASSERT_EQ(sizeof(1234), a.size());

    a = std::string("foobar");
    ASSERT_EQ(sizeof(std::string), a.size());

    a.reset();
    ASSERT_EQ(0, a.size());
}

struct CallCounter
{
    CallCounter() { default_constructions++; }
    CallCounter(const CallCounter&) { copy_constructions++; }
    CallCounter(CallCounter&&) { move_constructions++; }
    ~CallCounter() { destructions++; }

    static void reset_counters()
    {
        default_constructions = 0;
        copy_constructions = 0;
        move_constructions = 0;
        destructions = 0;
    }

    static int default_constructions;
    static int copy_constructions;
    static int move_constructions;
    static int destructions;
};

int CallCounter::default_constructions = 0;
int CallCounter::copy_constructions = 0;
int CallCounter::move_constructions = 0;
int CallCounter::destructions = 0;

TEST(any, default_constructed_is_empty)
{
    static_any<16> a;
    ASSERT_TRUE(a.empty());
}

TEST(any, contructed_with_param_non_empty)
{
    static_any<16> a(77); // will contain integer
    ASSERT_FALSE(a.empty());
}

TEST(any, has)
{
    static_any<16> a(77); // will contain integer
    ASSERT_TRUE(a.has<int>());
    ASSERT_FALSE(a.has<double>());
}

TEST(any, move_construct)
{
    CallCounter::reset_counters();
    CallCounter counter;
    static_any<16> a(std::move(counter));

    ASSERT_EQ(1, CallCounter::default_constructions);
    ASSERT_EQ(0, CallCounter::copy_constructions);
    ASSERT_EQ(1, CallCounter::move_constructions);
    ASSERT_EQ(0, CallCounter::destructions);
}

TEST(any, copy_construct)
{
    CallCounter::reset_counters();
    CallCounter counter;
    static_any<16> a(counter);

    ASSERT_EQ(1, CallCounter::default_constructions);
    ASSERT_EQ(1, CallCounter::copy_constructions);
    ASSERT_EQ(0, CallCounter::move_constructions);
    ASSERT_EQ(0, CallCounter::destructions);
}

TEST(any, destruction)
{
    CallCounter::reset_counters();
    CallCounter counter;
    {
        static_any<16> a(counter);
    }

    ASSERT_EQ(1, CallCounter::destructions);
}

TEST(any, reset_destruction)
{
    CallCounter::reset_counters();
    CallCounter counter;

    static_any<16> a(counter);
    a.reset();

    ASSERT_EQ(1, CallCounter::destructions);
}

TEST(any, copy_assignment)
{
    CallCounter::reset_counters();
    CallCounter counter;

    static_any<16> a(1);
    a = counter;

    ASSERT_EQ(1, CallCounter::default_constructions);
    ASSERT_EQ(1, CallCounter::copy_constructions);
    ASSERT_EQ(0, CallCounter::move_constructions);
}

TEST(any, move_assignment)
{
    CallCounter::reset_counters();
    CallCounter counter;

    static_any<16> a;
    a = std::move(counter);

    ASSERT_EQ(1, CallCounter::default_constructions);
    ASSERT_EQ(0, CallCounter::copy_constructions);
    ASSERT_EQ(1, CallCounter::move_constructions);
}

TEST(any, reassignment)
{
    CallCounter::reset_counters();
    CallCounter counter;

    static_any<16> a(counter);
    a = counter;

    ASSERT_EQ(1, CallCounter::default_constructions);
    ASSERT_EQ(2, CallCounter::copy_constructions);
    ASSERT_EQ(0, CallCounter::move_constructions);
    ASSERT_EQ(1, CallCounter::destructions);
}

TEST(any, not_empty_after_assignment)
{
    static_any<16> a;
    ASSERT_TRUE(a.empty());
    a = 7;
    ASSERT_FALSE(a.empty());
}

TEST(any, different_type_after_assignment)
{
    static_any<16> a(7);
    ASSERT_TRUE(a.has<int>());
    ASSERT_FALSE(a.has<double>());
    a = 3.14;
    ASSERT_FALSE(a.has<int>());
    ASSERT_TRUE(a.has<double>());
}

TEST(any, get_good_type)
{
    static_any<16> a(7);
    auto i = a.get<int>();
    ASSERT_EQ(7, i);
}

TEST(any, get_bad_type)
{
    static_any<16> a(7);
    EXPECT_THROW(a.get<double>(), std::bad_cast);
}

TEST(any, get_empty)
{
    static_any<16> a;
    EXPECT_THROW(a.get<double>(), std::bad_cast);
}

TEST(any, cast_empty)
{
    static_any<16> a;
    EXPECT_THROW(any_cast<int>(a), std::bad_cast);
}

TEST(any, mutable_get)
{
    static_any<16> a(7);
    a.get<int>() = 6;
    const static_any<16>& const_ref = a;
    auto i = const_ref.get<int>();
    ASSERT_EQ(6, i);
}

TEST(any, any_to_any_copy_uninitialized)
{
    static_any<16> a;
    static_any<16> b(a);

    ASSERT_TRUE(a.empty());
    ASSERT_TRUE(b.empty());
}

TEST(any, any_to_any_copy_construction)
{
    static_any<16> a(7);
    static_any<16> b(a);

    ASSERT_EQ(7, a.get<int>());
    ASSERT_EQ(7, b.get<int>());
}

TEST(any, any_to_any_assignment)
{
    static_any<32> a(std::string("Hello"));
    static_any<32> b;

    ASSERT_TRUE(b.empty());
    b = a;
    ASSERT_FALSE(b.empty());

    ASSERT_EQ("Hello", b.get<std::string>());
    ASSERT_EQ("Hello", a.get<std::string>());
}

TEST(any, any_to_any_move_construction)
{
    static_any<32> a(std::string("Hello"));
    static_any<32> b = std::move(a);

    ASSERT_FALSE(a.empty());
    ASSERT_FALSE(b.empty());

    ASSERT_EQ("Hello", b.get<std::string>());
}

TEST(any, any_to_bigger_any)
{
    static_any<16> a(1);
    ASSERT_EQ(1, a.get<int>());

    static_any<32> b(2);
    b = a;

    ASSERT_EQ(1, b.get<int>());
}

TEST(any, any_to_bigger_any_copy)
{
    static_any<16> a(1);
    ASSERT_EQ(1, a.get<int>());

    static_any<32> b = a;
    ASSERT_EQ(1, b.get<int>());
}

struct InitCtor
{
    int x = 1;
    int y = 2;
    InitCtor() = default;
    InitCtor(int x, int y) : x(x), y(y) {}
};

TEST(any, emplace_no_params)
{
    static_any<32> a;
    a.emplace<InitCtor>();

    ASSERT_FALSE(a.empty());
    EXPECT_EQ(1, a.get<InitCtor>().x);
    EXPECT_EQ(2, a.get<InitCtor>().y);
}

TEST(any, emplace_params)
{
    static_any<32> a;
    a.emplace<InitCtor>(77, 88);

    ASSERT_FALSE(a.empty());
    EXPECT_EQ(77, a.get<InitCtor>().x);
    EXPECT_EQ(88, a.get<InitCtor>().y);
}

TEST(any, destroyed_after_emplace)
{
    CallCounter::reset_counters();
    {
        static_any<32> a;
        a.emplace<CallCounter>();
    }

    EXPECT_EQ(1, CallCounter::default_constructions);
    EXPECT_EQ(1, CallCounter::destructions);
}

TEST(any, any_cast_pointer_correct_type)
{
    static_any<16> a(7);
    ASSERT_EQ(7, *any_cast<int>(&a));
}

TEST(any, any_cast_pointer_constness)
{
    static_any<16> a(7);
    const auto* a2 = &a;

    auto* pv  = any_cast<int>(&a);
    auto* pv2 = any_cast<int>(a2);

    ASSERT_FALSE(std::is_const<std::remove_pointer<decltype(pv)>::type>::value);
    ASSERT_TRUE(std::is_const<std::remove_pointer<decltype(pv2)>::type>::value);

    ASSERT_EQ(7, *pv);
    ASSERT_EQ(7, *pv2);
}

TEST(any, any_cast_pointer_wrong_type)
{
    static_any<16> a(7);
    ASSERT_EQ(nullptr, any_cast<float>(&a));
}

TEST(any, any_cast_reference_correct_type)
{
    static_any<16> a(7);
    ASSERT_EQ(7, any_cast<int>(a));
}

TEST(any, any_cast_reference_constness)
{
    static_any<16> a(7);
    const auto& a2 = a;

    auto& pv = any_cast<int>(a);
    auto& pv2 = any_cast<int>(a2);

    ASSERT_FALSE(std::is_const<std::remove_reference<decltype(pv)>::type>::value);
    ASSERT_TRUE(std::is_const<std::remove_reference<decltype(pv2)>::type>::value);

    ASSERT_EQ(7, pv);
    ASSERT_EQ(7, pv2);
}

TEST(any, any_cast_reference_wrong_type)
{
    static_any<16> a(7);
    EXPECT_THROW(any_cast<float>(a), bad_any_cast);
}

TEST(any, any_cast_reference_wrong_type_from_to)
{
    static_any<16> a(7);

    try {
        auto f = any_cast<float>(a);
        FAIL();
        ASSERT_EQ(.1234, f); // to avoid a warning, never reached
    }
    catch(bad_any_cast& ex) {
        ASSERT_EQ(typeid(int), ex.stored_type());
        ASSERT_EQ(typeid(float), ex.target_type());
    }
}

TEST(any, query_type)
{
    static_any<32> a(7);
    ASSERT_EQ(typeid(int), a.type());

    a = std::string("f00");
    ASSERT_EQ(typeid(std::string), a.type());
}

TEST(any, reset_empty)
{
    static_any<16> a(7);
    ASSERT_FALSE(a.empty());
    a.reset();
    ASSERT_TRUE(a.empty());
}

TEST(any, reset_has)
{
    static_any<16> a(7);
    ASSERT_TRUE(a.has<int>());
    a.reset();
    ASSERT_FALSE(a.has<int>());
}

TEST(any, type_identification_across_dll)
{
    auto a = get_any_with_int(7);
    EXPECT_TRUE(a.has<int>());
    EXPECT_FALSE(a.has<std::string>());

    EXPECT_EQ(7, a.get<int>());

    EXPECT_THROW(a.get<std::string>(), bad_any_cast);
}

TEST(any_t, simple)
{
    static_any_t<16> a(7);
    ASSERT_EQ(7, a.get<int>());
}

struct unsafe_to_copy
{
    unsafe_to_copy() =default;
    unsafe_to_copy(const unsafe_to_copy&) { throw 123; }
};

TEST(any_exception, init)
{
    EXPECT_THROW(static_any<16> a = unsafe_to_copy(), int);
}

TEST(any_exception, move)
{
    static_any<16> a;

    EXPECT_THROW(a = unsafe_to_copy(), int);
    EXPECT_TRUE(a.empty());
}

TEST(any_exception, copy)
{
    static_any<16> a;
    unsafe_to_copy u;

    EXPECT_THROW(a = u, int);
    EXPECT_TRUE(a.empty());
}

struct unsafe_to_construct
{
    unsafe_to_construct() { throw 123; };
};

TEST(any_exception, emplace)
{
    static_any<16> a;
    EXPECT_THROW(a.emplace<unsafe_to_construct>(), int);
    EXPECT_TRUE(a.empty());
}

<|endoftext|>


<commit_before>// Copyright (c) 2009-2012 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include <boost/assign/list_of.hpp> // for 'map_list_of()'
#include <boost/foreach.hpp>

#include "checkpoints.h"

#include "main.h"
#include "uint256.h"

namespace Checkpoints
{
    typedef std::map<int, uint256> MapCheckpoints;

    // How many times we expect transactions after the last checkpoint to
    // be slower. This number is a compromise, as it can't be accurate for
    // every system. When reindexing from a fast disk with a slow CPU, it
    // can be up to 20, while when downloading from a slow network with a
    // fast multicore CPU, it won't be much higher than 1.
    static const double fSigcheckVerificationFactor = 5.0;

    struct CCheckpointData {
        const MapCheckpoints *mapCheckpoints;
        int64 nTimeLastCheckpoint;
        int64 nTransactionsLastCheckpoint;
        double fTransactionsPerDay;
    };

    // What makes a good checkpoint block?
    // + Is surrounded by blocks with reasonable timestamps
    //   (no blocks before with a timestamp after, none after with
    //    timestamp before)
    // + Contains no strange transactions
    static MapCheckpoints mapCheckpoints =
        boost::assign::map_list_of
        (  0, uint256("0x91ec5f25ee9a0ffa1af7d4da4db9a552228dd2dc77cdb15b738be4e1f55f30ee"))
        ;
    static const CCheckpointData data = {
        &mapCheckpoints,
        1392757140, // * UNIX timestamp of last checkpoint block
        0,    // * total number of transactions between genesis and last checkpoint
                    //   (the tx=... number in the SetBestChain debug.log lines)
        8000.0     // * estimated number of transactions per day after checkpoint
    };

    static MapCheckpoints mapCheckpointsTestnet =
        boost::assign::map_list_of
        (   0, uint256("91ec5f25ee9a0ffa1af7d4da4db9a552228dd2dc77cdb15b738be4e1f55f30ee"))
        ;
    static const CCheckpointData dataTestnet = {
        &mapCheckpointsTestnet,
        1369685559,
        37581,
        300
    };

    const CCheckpointData &Checkpoints() {
        if (fTestNet)
            return dataTestnet;
        else
            return data;
    }

    bool CheckBlock(int nHeight, const uint256& hash)
    {
        if (fTestNet) return true; // Testnet has no checkpoints
        if (!GetBoolArg("-checkpoints", true))
            return true;

        const MapCheckpoints& checkpoints = *Checkpoints().mapCheckpoints;

        MapCheckpoints::const_iterator i = checkpoints.find(nHeight);
        if (i == checkpoints.end()) return true;
        return hash == i->second;
    }

    // Guess how far we are in the verification process at the given block index
    double GuessVerificationProgress(CBlockIndex *pindex) {
        if (pindex==NULL)
            return 0.0;

        int64 nNow = time(NULL);

        double fWorkBefore = 0.0; // Amount of work done before pindex
        double fWorkAfter = 0.0;  // Amount of work left after pindex (estimated)
        // Work is defined as: 1.0 per transaction before the last checkoint, and
        // fSigcheckVerificationFactor per transaction after.

        const CCheckpointData &data = Checkpoints();

        if (pindex->nChainTx <= data.nTransactionsLastCheckpoint) {
            double nCheapBefore = pindex->nChainTx;
            double nCheapAfter = data.nTransactionsLastCheckpoint - pindex->nChainTx;
            double nExpensiveAfter = (nNow - data.nTimeLastCheckpoint)/86400.0*data.fTransactionsPerDay;
            fWorkBefore = nCheapBefore;
            fWorkAfter = nCheapAfter + nExpensiveAfter*fSigcheckVerificationFactor;
        } else {
            double nCheapBefore = data.nTransactionsLastCheckpoint;
            double nExpensiveBefore = pindex->nChainTx - data.nTransactionsLastCheckpoint;
            double nExpensiveAfter = (nNow - pindex->nTime)/86400.0*data.fTransactionsPerDay;
            fWorkBefore = nCheapBefore + nExpensiveBefore*fSigcheckVerificationFactor;
            fWorkAfter = nExpensiveAfter*fSigcheckVerificationFactor;
        }

        return fWorkBefore / (fWorkBefore + fWorkAfter);
    }

    int GetTotalBlocksEstimate()
    {
        if (fTestNet) return 0; // Testnet has no checkpoints
        if (!GetBoolArg("-checkpoints", true))
            return 0;

        const MapCheckpoints& checkpoints = *Checkpoints().mapCheckpoints;

        return checkpoints.rbegin()->first;
    }

    CBlockIndex* GetLastCheckpoint(const std::map<uint256, CBlockIndex*>& mapBlockIndex)
    {
        if (fTestNet) return NULL; // Testnet has no checkpoints
        if (!GetBoolArg("-checkpoints", true))
            return NULL;

        const MapCheckpoints& checkpoints = *Checkpoints().mapCheckpoints;

        BOOST_REVERSE_FOREACH(const MapCheckpoints::value_type& i, checkpoints)
        {
            const uint256& hash = i.second;
            std::map<uint256, CBlockIndex*>::const_iterator t = mapBlockIndex.find(hash);
            if (t != mapBlockIndex.end())
                return t->second;
        }
        return NULL;
    }
}
<commit_msg>Add Frist Checkpoints<commit_after>// Copyright (c) 2009-2012 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include <boost/assign/list_of.hpp> // for 'map_list_of()'
#include <boost/foreach.hpp>

#include "checkpoints.h"

#include "main.h"
#include "uint256.h"

namespace Checkpoints
{
    typedef std::map<int, uint256> MapCheckpoints;

    // How many times we expect transactions after the last checkpoint to
    // be slower. This number is a compromise, as it can't be accurate for
    // every system. When reindexing from a fast disk with a slow CPU, it
    // can be up to 20, while when downloading from a slow network with a
    // fast multicore CPU, it won't be much higher than 1.
    static const double fSigcheckVerificationFactor = 5.0;

    struct CCheckpointData {
        const MapCheckpoints *mapCheckpoints;
        int64 nTimeLastCheckpoint;
        int64 nTransactionsLastCheckpoint;
        double fTransactionsPerDay;
    };

    // What makes a good checkpoint block?
    // + Is surrounded by blocks with reasonable timestamps
    //   (no blocks before with a timestamp after, none after with
    //    timestamp before)
    // + Contains no strange transactions
    static MapCheckpoints mapCheckpoints =
        boost::assign::map_list_of
        (     0, uint256("0x91ec5f25ee9a0ffa1af7d4da4db9a552228dd2dc77cdb15b738be4e1f55f30ee"))
		(  4506, uint256("0x71d4d0454e12191a77078d42f09bef60e8687a9fe3890cbb42d77151f8d55683"))
        ;
    static const CCheckpointData data = {
        &mapCheckpoints,
        1392757140, // * UNIX timestamp of last checkpoint block
        4516,    // * total number of transactions between genesis and last checkpoint
                    //   (the tx=... number in the SetBestChain debug.log lines)
        8000.0     // * estimated number of transactions per day after checkpoint
    };

    static MapCheckpoints mapCheckpointsTestnet =
        boost::assign::map_list_of
        (   0, uint256("91ec5f25ee9a0ffa1af7d4da4db9a552228dd2dc77cdb15b738be4e1f55f30ee"))
        ;
    static const CCheckpointData dataTestnet = {
        &mapCheckpointsTestnet,
        1369685559,
        37581,
        300
    };

    const CCheckpointData &Checkpoints() {
        if (fTestNet)
            return dataTestnet;
        else
            return data;
    }

    bool CheckBlock(int nHeight, const uint256& hash)
    {
        if (fTestNet) return true; // Testnet has no checkpoints
        if (!GetBoolArg("-checkpoints", true))
            return true;

        const MapCheckpoints& checkpoints = *Checkpoints().mapCheckpoints;

        MapCheckpoints::const_iterator i = checkpoints.find(nHeight);
        if (i == checkpoints.end()) return true;
        return hash == i->second;
    }

    // Guess how far we are in the verification process at the given block index
    double GuessVerificationProgress(CBlockIndex *pindex) {
        if (pindex==NULL)
            return 0.0;

        int64 nNow = time(NULL);

        double fWorkBefore = 0.0; // Amount of work done before pindex
        double fWorkAfter = 0.0;  // Amount of work left after pindex (estimated)
        // Work is defined as: 1.0 per transaction before the last checkoint, and
        // fSigcheckVerificationFactor per transaction after.

        const CCheckpointData &data = Checkpoints();

        if (pindex->nChainTx <= data.nTransactionsLastCheckpoint) {
            double nCheapBefore = pindex->nChainTx;
            double nCheapAfter = data.nTransactionsLastCheckpoint - pindex->nChainTx;
            double nExpensiveAfter = (nNow - data.nTimeLastCheckpoint)/86400.0*data.fTransactionsPerDay;
            fWorkBefore = nCheapBefore;
            fWorkAfter = nCheapAfter + nExpensiveAfter*fSigcheckVerificationFactor;
        } else {
            double nCheapBefore = data.nTransactionsLastCheckpoint;
            double nExpensiveBefore = pindex->nChainTx - data.nTransactionsLastCheckpoint;
            double nExpensiveAfter = (nNow - pindex->nTime)/86400.0*data.fTransactionsPerDay;
            fWorkBefore = nCheapBefore + nExpensiveBefore*fSigcheckVerificationFactor;
            fWorkAfter = nExpensiveAfter*fSigcheckVerificationFactor;
        }

        return fWorkBefore / (fWorkBefore + fWorkAfter);
    }

    int GetTotalBlocksEstimate()
    {
        if (fTestNet) return 0; // Testnet has no checkpoints
        if (!GetBoolArg("-checkpoints", true))
            return 0;

        const MapCheckpoints& checkpoints = *Checkpoints().mapCheckpoints;

        return checkpoints.rbegin()->first;
    }

    CBlockIndex* GetLastCheckpoint(const std::map<uint256, CBlockIndex*>& mapBlockIndex)
    {
        if (fTestNet) return NULL; // Testnet has no checkpoints
        if (!GetBoolArg("-checkpoints", true))
            return NULL;

        const MapCheckpoints& checkpoints = *Checkpoints().mapCheckpoints;

        BOOST_REVERSE_FOREACH(const MapCheckpoints::value_type& i, checkpoints)
        {
            const uint256& hash = i.second;
            std::map<uint256, CBlockIndex*>::const_iterator t = mapBlockIndex.find(hash);
            if (t != mapBlockIndex.end())
                return t->second;
        }
        return NULL;
    }
}
<|endoftext|>