<commit_before>
// The libMesh Finite Element Library.
// Copyright (C) 2002-2012 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner

// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.

// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.

// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

// C++ includes
#include <algorithm> // for std::fill
#include <cstdlib> // *must* precede <cmath> for proper std:abs() on PGI, Sun Studio CC
#include <cmath>     // for std::sqrt std::pow std::abs

// Local Includes
#include "libmesh/libmesh_common.h"
#include "libmesh/patch.h"
#include "libmesh/elem.h"

namespace libMesh
{

//-----------------------------------------------------------------
// Patch implementations
void Patch::find_face_neighbors(std::set<const Elem *> &new_neighbors)
{
  // Loop over all the elements in the patch
  std::set<const Elem*>::const_iterator       it  = this->begin();
  const std::set<const Elem*>::const_iterator end = this->end();

  for (; it != end; ++it)
    {
      const Elem* elem = *it;
      for (unsigned int s=0; s<elem->n_sides(); s++)
        if (elem->neighbor(s) != NULL)        // we have a neighbor on this side
          {
	    const Elem* neighbor = elem->neighbor(s);

#ifdef LIBMESH_ENABLE_AMR
	    if (!neighbor->active())          // the neighbor is *not* active,
	      {                               // so add *all* neighboring
                                              // active children to the patch
	        std::vector<const Elem*> active_neighbor_children;

	        neighbor->active_family_tree_by_neighbor
                  (active_neighbor_children, elem);

                std::vector<const Elem*>::const_iterator
                  child_it  = active_neighbor_children.begin();
                const std::vector<const Elem*>::const_iterator
                  child_end = active_neighbor_children.end();
                for (; child_it != child_end; ++child_it)
		  new_neighbors.insert(*child_it);
	      }
            else
#endif // #ifdef LIBMESH_ENABLE_AMR
	      new_neighbors.insert (neighbor); // add active neighbors
          }
    }
}

void Patch::add_face_neighbors()
{
  std::set<const Elem *> new_neighbors;

  this->find_face_neighbors(new_neighbors);

  this->insert(new_neighbors.begin(), new_neighbors.end());
}

void Patch::add_local_face_neighbors()
{
  std::set<const Elem *> new_neighbors;

  this->find_face_neighbors(new_neighbors);

  std::set<const Elem*>::const_iterator       it  = new_neighbors.begin();
  const std::set<const Elem*>::const_iterator end = new_neighbors.end();

  for (; it != end; ++it)
    {
      const Elem* neighbor = *it;
      if (neighbor->processor_id() ==
	  libMesh::processor_id()) // ... if the neighbor belongs to this processor
	this->insert (neighbor);   // ... then add it to the patch
    }
}

void Patch::add_semilocal_face_neighbors()
{
  std::set<const Elem *> new_neighbors;

  this->find_face_neighbors(new_neighbors);

  std::set<const Elem*>::const_iterator       it  = new_neighbors.begin();
  const std::set<const Elem*>::const_iterator end = new_neighbors.end();

  for (; it != end; ++it)
    {
      const Elem* neighbor = *it;
      if (neighbor->is_semilocal())
	this->insert (neighbor);
    }
}

void Patch::find_point_neighbors(std::set<const Elem *> &new_neighbors)
{
  // Loop over all the elements in the patch
  std::set<const Elem*>::const_iterator       it  = this->begin();
  const std::set<const Elem*>::const_iterator end = this->end();

  for (; it != end; ++it)
    {
      std::set<const Elem*> elem_point_neighbors;

      const Elem* elem = *it;
      elem->find_point_neighbors(elem_point_neighbors);

      new_neighbors.insert(elem_point_neighbors.begin(),
                           elem_point_neighbors.end());
    }
}

void Patch::add_point_neighbors()
{
  std::set<const Elem *> new_neighbors;

  this->find_point_neighbors(new_neighbors);

  this->insert(new_neighbors.begin(), new_neighbors.end());
}

void Patch::add_local_point_neighbors()
{
  std::set<const Elem *> new_neighbors;

  this->find_point_neighbors(new_neighbors);

  std::set<const Elem*>::const_iterator       it  = new_neighbors.begin();
  const std::set<const Elem*>::const_iterator end = new_neighbors.end();

  for (; it != end; ++it)
    {
      const Elem* neighbor = *it;
      if (neighbor->processor_id() ==
	  libMesh::processor_id()) // ... if the neighbor belongs to this processor
	this->insert (neighbor);   // ... then add it to the patch
    }
}

void Patch::add_semilocal_point_neighbors()
{
  std::set<const Elem *> new_neighbors;

  this->find_point_neighbors(new_neighbors);

  std::set<const Elem*>::const_iterator       it  = new_neighbors.begin();
  const std::set<const Elem*>::const_iterator end = new_neighbors.end();

  for (; it != end; ++it)
    {
      const Elem* neighbor = *it;
      if (neighbor->is_semilocal())
	this->insert (neighbor);
    }
}

void Patch::build_around_element (const Elem* e0,
                                  const unsigned int target_patch_size,
                                  PMF patchtype)
{

  // Make sure we are building a patch for an active element.
  libmesh_assert(e0);
  libmesh_assert (e0->active());
  // Make sure we are either starting with a local element or
  // requesting a nonlocal patch
  libmesh_assert ((patchtype != &Patch::add_local_face_neighbors &&
           patchtype != &Patch::add_local_point_neighbors) ||
           e0->processor_id() == libMesh::processor_id());

  // First clear the current set, then add the element of interest.
  this->clear();
  this->insert (e0);

  // Repeatedly add the neighbors of the elements in the patch until
  // the target patch size is met
  while (this->size() < target_patch_size)
    {
      // It is possible that the target patch size is larger than the number
      // of elements that can be added to the patch.  Since we don't
      // have access to the Mesh object here, the only way we can
      // detect this case is by detecting a "stagnant patch," i.e. a
      // patch whose size does not increase after adding face neighbors
      const std::size_t old_patch_size = this->size();

      // We profile the patch-extending functions separately
      (this->*patchtype)();

      // Check for a "stagnant" patch
      if (this->size() == old_patch_size)
	{
	  libmesh_do_once(libMesh::err <<
            "WARNING: stagnant patch of " << this->size() << " elements."
            << std::endl <<
            "Does the target patch size exceed the number of local elements?"
	    << std::endl;
	  libmesh_here(););
	  break;
	}
    } // end while loop

  // make sure all the elements in the patch are active and local
  // if we are in debug mode
#ifdef DEBUG
  {
    std::set<const Elem*>::const_iterator       it  = this->begin();
    const std::set<const Elem*>::const_iterator end = this->end();

    for (; it != end; ++it)
      {
	// Convenience.  Keep the syntax simple.
	const Elem* elem = *it;

	libmesh_assert (elem->active());
        if ((patchtype == &Patch::add_local_face_neighbors ||
             patchtype == &Patch::add_local_point_neighbors))
	  libmesh_assert_equal_to (elem->processor_id(), libMesh::processor_id());
      }
  }
#endif

}

} // namespace libMesh
<commit_msg>Changes in patch.C for -Wshadow.<commit_after>
// The libMesh Finite Element Library.
// Copyright (C) 2002-2012 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner

// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.

// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.

// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

// C++ includes
#include <algorithm> // for std::fill
#include <cstdlib> // *must* precede <cmath> for proper std:abs() on PGI, Sun Studio CC
#include <cmath>     // for std::sqrt std::pow std::abs

// Local Includes
#include "libmesh/libmesh_common.h"
#include "libmesh/patch.h"
#include "libmesh/elem.h"

namespace libMesh
{

//-----------------------------------------------------------------
// Patch implementations
void Patch::find_face_neighbors(std::set<const Elem *> &new_neighbors)
{
  // Loop over all the elements in the patch
  std::set<const Elem*>::const_iterator       it  = this->begin();
  const std::set<const Elem*>::const_iterator end_it = this->end();

  for (; it != end_it; ++it)
    {
      const Elem* elem = *it;
      for (unsigned int s=0; s<elem->n_sides(); s++)
        if (elem->neighbor(s) != NULL)        // we have a neighbor on this side
          {
	    const Elem* neighbor = elem->neighbor(s);

#ifdef LIBMESH_ENABLE_AMR
	    if (!neighbor->active())          // the neighbor is *not* active,
	      {                               // so add *all* neighboring
                                              // active children to the patch
	        std::vector<const Elem*> active_neighbor_children;

	        neighbor->active_family_tree_by_neighbor
                  (active_neighbor_children, elem);

                std::vector<const Elem*>::const_iterator
                  child_it  = active_neighbor_children.begin();
                const std::vector<const Elem*>::const_iterator
                  child_end = active_neighbor_children.end();
                for (; child_it != child_end; ++child_it)
		  new_neighbors.insert(*child_it);
	      }
            else
#endif // #ifdef LIBMESH_ENABLE_AMR
	      new_neighbors.insert (neighbor); // add active neighbors
          }
    }
}

void Patch::add_face_neighbors()
{
  std::set<const Elem *> new_neighbors;

  this->find_face_neighbors(new_neighbors);

  this->insert(new_neighbors.begin(), new_neighbors.end());
}

void Patch::add_local_face_neighbors()
{
  std::set<const Elem *> new_neighbors;

  this->find_face_neighbors(new_neighbors);

  std::set<const Elem*>::const_iterator       it  = new_neighbors.begin();
  const std::set<const Elem*>::const_iterator end_it = new_neighbors.end();

  for (; it != end_it; ++it)
    {
      const Elem* neighbor = *it;
      if (neighbor->processor_id() ==
	  libMesh::processor_id()) // ... if the neighbor belongs to this processor
	this->insert (neighbor);   // ... then add it to the patch
    }
}

void Patch::add_semilocal_face_neighbors()
{
  std::set<const Elem *> new_neighbors;

  this->find_face_neighbors(new_neighbors);

  std::set<const Elem*>::const_iterator       it  = new_neighbors.begin();
  const std::set<const Elem*>::const_iterator end_it = new_neighbors.end();

  for (; it != end_it; ++it)
    {
      const Elem* neighbor = *it;
      if (neighbor->is_semilocal())
	this->insert (neighbor);
    }
}

void Patch::find_point_neighbors(std::set<const Elem *> &new_neighbors)
{
  // Loop over all the elements in the patch
  std::set<const Elem*>::const_iterator       it  = this->begin();
  const std::set<const Elem*>::const_iterator end_it = this->end();

  for (; it != end_it; ++it)
    {
      std::set<const Elem*> elem_point_neighbors;

      const Elem* elem = *it;
      elem->find_point_neighbors(elem_point_neighbors);

      new_neighbors.insert(elem_point_neighbors.begin(),
                           elem_point_neighbors.end());
    }
}

void Patch::add_point_neighbors()
{
  std::set<const Elem *> new_neighbors;

  this->find_point_neighbors(new_neighbors);

  this->insert(new_neighbors.begin(), new_neighbors.end());
}

void Patch::add_local_point_neighbors()
{
  std::set<const Elem *> new_neighbors;

  this->find_point_neighbors(new_neighbors);

  std::set<const Elem*>::const_iterator       it  = new_neighbors.begin();
  const std::set<const Elem*>::const_iterator end_it = new_neighbors.end();

  for (; it != end_it; ++it)
    {
      const Elem* neighbor = *it;
      if (neighbor->processor_id() ==
	  libMesh::processor_id()) // ... if the neighbor belongs to this processor
	this->insert (neighbor);   // ... then add it to the patch
    }
}

void Patch::add_semilocal_point_neighbors()
{
  std::set<const Elem *> new_neighbors;

  this->find_point_neighbors(new_neighbors);

  std::set<const Elem*>::const_iterator       it  = new_neighbors.begin();
  const std::set<const Elem*>::const_iterator end_it = new_neighbors.end();

  for (; it != end_it; ++it)
    {
      const Elem* neighbor = *it;
      if (neighbor->is_semilocal())
	this->insert (neighbor);
    }
}

void Patch::build_around_element (const Elem* e0,
                                  const unsigned int target_patch_size,
                                  PMF patchtype)
{

  // Make sure we are building a patch for an active element.
  libmesh_assert(e0);
  libmesh_assert (e0->active());
  // Make sure we are either starting with a local element or
  // requesting a nonlocal patch
  libmesh_assert ((patchtype != &Patch::add_local_face_neighbors &&
           patchtype != &Patch::add_local_point_neighbors) ||
           e0->processor_id() == libMesh::processor_id());

  // First clear the current set, then add the element of interest.
  this->clear();
  this->insert (e0);

  // Repeatedly add the neighbors of the elements in the patch until
  // the target patch size is met
  while (this->size() < target_patch_size)
    {
      // It is possible that the target patch size is larger than the number
      // of elements that can be added to the patch.  Since we don't
      // have access to the Mesh object here, the only way we can
      // detect this case is by detecting a "stagnant patch," i.e. a
      // patch whose size does not increase after adding face neighbors
      const std::size_t old_patch_size = this->size();

      // We profile the patch-extending functions separately
      (this->*patchtype)();

      // Check for a "stagnant" patch
      if (this->size() == old_patch_size)
	{
	  libmesh_do_once(libMesh::err <<
            "WARNING: stagnant patch of " << this->size() << " elements."
            << std::endl <<
            "Does the target patch size exceed the number of local elements?"
	    << std::endl;
	  libmesh_here(););
	  break;
	}
    } // end while loop

  // make sure all the elements in the patch are active and local
  // if we are in debug mode
#ifdef DEBUG
  {
    std::set<const Elem*>::const_iterator       it  = this->begin();
    const std::set<const Elem*>::const_iterator end_it = this->end();

    for (; it != end_it; ++it)
      {
	// Convenience.  Keep the syntax simple.
	const Elem* elem = *it;

	libmesh_assert (elem->active());
        if ((patchtype == &Patch::add_local_face_neighbors ||
             patchtype == &Patch::add_local_point_neighbors))
	  libmesh_assert_equal_to (elem->processor_id(), libMesh::processor_id());
      }
  }
#endif

}

} // namespace libMesh
<|endoftext|>


<commit_before>#include "ms_layer.hpp"
#include "ms_hashtable.hpp"
#include "ms_projection.hpp"

Nan::Persistent<v8::FunctionTemplate> MSLayer::constructor;

void MSLayer::Initialize(v8::Local<v8::Object> target) {
  v8::Local<v8::FunctionTemplate> tpl = Nan::New <v8::FunctionTemplate>(MSLayer::New);
  tpl->InstanceTemplate()->SetInternalFieldCount(1);
  tpl->SetClassName(Nan::New("Layer").ToLocalChecked());

  Nan::SetPrototypeMethod(tpl, "getGridIntersectionCoordinates", GetGridIntersectionCoordinates);
  Nan::SetPrototypeMethod(tpl, "updateFromString", UpdateFromString);
#if MS_VERSION_NUM >= 60400
  Nan::SetPrototypeMethod(tpl, "toString", ToString);
#endif

  RW_ATTR(tpl, "name", PropertyGetter, PropertySetter);
  RW_ATTR(tpl, "status", PropertyGetter, PropertySetter);
  RW_ATTR(tpl, "type", PropertyGetter, PropertySetter);
  RW_ATTR(tpl, "connection", PropertyGetter, PropertySetter);
  RW_ATTR(tpl, "minscaledenom", PropertyGetter, PropertySetter);
  RW_ATTR(tpl, "maxscaledenom", PropertyGetter, PropertySetter);
  RW_ATTR(tpl, "projection", PropertyGetter, PropertySetter);
  RW_ATTR(tpl, "units", PropertyGetter, PropertySetter);
  RO_ATTR(tpl, "connectiontype", PropertyGetter);
  RO_ATTR(tpl, "metadata", PropertyGetter);

  target->Set(Nan::New("Layer").ToLocalChecked(), tpl->GetFunction());
  constructor.Reset(tpl);
}

MSLayer::MSLayer(layerObj *layer) : ObjectWrap(), this_(layer) {}

MSLayer::MSLayer() : ObjectWrap(), this_(0) {}

MSLayer::~MSLayer() { }

NAN_METHOD(MSLayer::New)
{
  MSLayer* obj;
  if (!info.IsConstructCall()) {
    Nan::ThrowError("Cannot call constructor as function, you need to use 'new' keyword");
    return;
  }

  if (info[0]->IsExternal()) {
    v8::Local<v8::External> ext = info[0].As<v8::External>();
    void *ptr = ext->Value();
    MSLayer *f =  static_cast<MSLayer *>(ptr);
    f->Wrap(info.This());
    info.GetReturnValue().Set(info.This());
    return;
  }

  if (info.Length() != 1 || !info[0]->IsString()) {
    Nan::ThrowTypeError("requires one argument: a string");
    return;
  }

  layerObj* layer = (layerObj*)calloc(1,sizeof(layerObj));
  initLayer(layer, (mapObj*)NULL);

  layer->name = strdup(TOSTR(info[0]));

  obj = new MSLayer(layer);
  obj->Wrap(info.This());
  info.GetReturnValue().Set(info.This());
}

v8::Local<v8::Value> MSLayer::NewInstance(layerObj *ptr) {
  Nan::EscapableHandleScope scope;
  MSLayer* obj = new MSLayer();
  obj->this_ = ptr;
  v8::Local<v8::Value> ext = Nan::New<v8::External>(obj);
  return scope.Escape(Nan::New(constructor)->GetFunction()->NewInstance(1, &ext));
}

NAN_GETTER(MSLayer::PropertyGetter) {

  MSLayer *obj = Nan::ObjectWrap::Unwrap<MSLayer>(info.Holder());

  if (STRCMP(property, "name")) {
    info.GetReturnValue().Set(Nan::New(obj->this_->name).ToLocalChecked());
  } else if (STRCMP(property, "status")) {
    info.GetReturnValue().Set(obj->this_->status);
  } else if (STRCMP(property, "metadata")) {
    info.GetReturnValue().Set(MSHashTable::NewInstance(&(obj->this_->metadata)));
  } else if (STRCMP(property, "type")) {
    info.GetReturnValue().Set(obj->this_->type);
  } else if (STRCMP(property, "minscaledenom")) {
    info.GetReturnValue().Set(obj->this_->minscaledenom);
  } else if (STRCMP(property, "maxscaledenom")) {
    info.GetReturnValue().Set(obj->this_->maxscaledenom);
  } else if (STRCMP(property, "units")) {
    info.GetReturnValue().Set(obj->this_->units);
  } else if (STRCMP(property, "projection")) {
    info.GetReturnValue().Set(MSProjection::NewInstance(&obj->this_->projection));
  } else if (STRCMP(property, "connection")) {
    if (obj->this_->connection == NULL) {
      info.GetReturnValue().Set(Nan::Undefined());
    } else {
      info.GetReturnValue().Set(Nan::New(obj->this_->connection).ToLocalChecked());
    }
  } else if (STRCMP(property, "connectiontype")) {
    info.GetReturnValue().Set(obj->this_->connectiontype);
  }
}

NAN_SETTER(MSLayer::PropertySetter) {
  MSLayer *obj = Nan::ObjectWrap::Unwrap<MSLayer>(info.Holder());

  if (STRCMP(property, "name")) {
    REPLACE_STRING(obj->this_->name, value)
  } else if (STRCMP(property, "status")) {
    obj->this_->status = value->NumberValue();
  } else if (STRCMP(property, "minscaledenom")) {
    obj->this_->minscaledenom = value->NumberValue();
  } else if (STRCMP(property, "maxscaledenom")) {
    obj->this_->maxscaledenom = value->NumberValue();
  } else if (STRCMP(property, "units")) {
    int32_t units = value->Int32Value();
    if (units >= MS_INCHES && units <= MS_NAUTICALMILES) {
      obj->this_->units = (MS_UNITS) units;
    }
  } else if (STRCMP(property, "projection")) {
    msLoadProjectionString(&(obj->this_->projection), TOSTR(value));
  } else if (STRCMP(property, "type")) {
    int32_t type = value->Int32Value();
    if (type >= MS_LAYER_ANNOTATION && type <= MS_LAYER_TILEINDEX) {
      obj->this_->type = (MS_LAYER_TYPE) type;
    }
  } else if (STRCMP(property, "connection")) {
    REPLACE_STRING(obj->this_->connection, value)
  }
}

NAN_METHOD(MSLayer::GetGridIntersectionCoordinates) {
  MSLayer *obj = Nan::ObjectWrap::Unwrap<MSLayer>(info.This());

  int i = 0;

  graticuleIntersectionObj *values = msGraticuleLayerGetIntersectionPoints(obj->this_->map, obj->this_);

  v8::Local<v8::Array> left = Nan::New<v8::Array>(values->nLeft);
  v8::Local<v8::Array> top = Nan::New<v8::Array>(values->nTop);
  v8::Local<v8::Array> right = Nan::New<v8::Array>(values->nRight);
  v8::Local<v8::Array> bottom = Nan::New<v8::Array>(values->nBottom);
  v8::Local<v8::Object> val = Nan::New<v8::Object>();

  for (i=0; i<values->nLeft; i++) {
    val->Set(Nan::New("x").ToLocalChecked(), Nan::New(values->pasLeft[i].x));
    val->Set(Nan::New("y").ToLocalChecked(), Nan::New(values->pasLeft[i].y));
    val->Set(Nan::New("label").ToLocalChecked(), Nan::New(values->papszLeftLabels[i]).ToLocalChecked());
    left->Set(i, val);
  }
  for (i=0; i<values->nTop; i++) {
    val = Nan::New<v8::Object>();
    val->Set(Nan::New("x").ToLocalChecked(), Nan::New(values->pasTop[i].x));
    val->Set(Nan::New("y").ToLocalChecked(), Nan::New(values->pasTop[i].y));
    val->Set(Nan::New("label").ToLocalChecked(), Nan::New(values->papszTopLabels[i]).ToLocalChecked());
    top->Set(i, val);
  }
  for (i=0; i<values->nRight; i++) {
    val = Nan::New<v8::Object>();
    val->Set(Nan::New("x").ToLocalChecked(), Nan::New(values->pasRight[i].x));
    val->Set(Nan::New("y").ToLocalChecked(), Nan::New(values->pasRight[i].y));
    val->Set(Nan::New("label").ToLocalChecked(), Nan::New(values->papszRightLabels[i]).ToLocalChecked());
    right->Set(i, val);
  }
  for (i=0; i<values->nBottom; i++) {
    val = Nan::New<v8::Object>();
    val->Set(Nan::New("x").ToLocalChecked(), Nan::New(values->pasBottom[i].x));
    val->Set(Nan::New("y").ToLocalChecked(), Nan::New(values->pasBottom[i].y));
    val->Set(Nan::New("label").ToLocalChecked(), Nan::New(values->papszBottomLabels[i]).ToLocalChecked());
    bottom->Set(i, val);
  }

  // return object like this:
  // {
  //   left: [{position: 0, label: '123.00'}],
  //   top: [{position: 0, label: '123.00'}],
  //   right: [{position: 0, label: '123.00'}],
  //   bottom: [{position: 0, label: '123.00'}],
  // }
  v8::Local<v8::Object> result = Nan::New<v8::Object>();
  result->Set(Nan::New("left").ToLocalChecked(), left);
  result->Set(Nan::New("top").ToLocalChecked(), top);
  result->Set(Nan::New("right").ToLocalChecked(), right);
  result->Set(Nan::New("bottom").ToLocalChecked(), bottom);
  info.GetReturnValue().Set(result);
}

NAN_METHOD(MSLayer::UpdateFromString) {
  MSLayer *obj = Nan::ObjectWrap::Unwrap<MSLayer>(info.This());
  int result;
  if (info.Length() < 1) {
    Nan::ThrowError("UpdateFromString requires one string argument");
    return;
  }
  if (!info[0]->IsString()) {
    Nan::ThrowError("UpdateFromString requires one string argument");
    return;
  }
  result = msUpdateLayerFromString(obj->this_, TOSTR(info[0]), MS_FALSE);
  info.GetReturnValue().Set(result);
}

#if MS_VERSION_NUM >= 60400
NAN_METHOD(MSLayer::ToString) {
  MSLayer *obj = Nan::ObjectWrap::Unwrap<MSLayer>(info.This());
  char *text = msWriteLayerToString(obj->this_);
  info.GetReturnValue().Set(Nan::New(text).ToLocalChecked());
}
#endif
<commit_msg>Fix missing object initializer in left grid coordinate computation.<commit_after>#include "ms_layer.hpp"
#include "ms_hashtable.hpp"
#include "ms_projection.hpp"

Nan::Persistent<v8::FunctionTemplate> MSLayer::constructor;

void MSLayer::Initialize(v8::Local<v8::Object> target) {
  v8::Local<v8::FunctionTemplate> tpl = Nan::New <v8::FunctionTemplate>(MSLayer::New);
  tpl->InstanceTemplate()->SetInternalFieldCount(1);
  tpl->SetClassName(Nan::New("Layer").ToLocalChecked());

  Nan::SetPrototypeMethod(tpl, "getGridIntersectionCoordinates", GetGridIntersectionCoordinates);
  Nan::SetPrototypeMethod(tpl, "updateFromString", UpdateFromString);
#if MS_VERSION_NUM >= 60400
  Nan::SetPrototypeMethod(tpl, "toString", ToString);
#endif

  RW_ATTR(tpl, "name", PropertyGetter, PropertySetter);
  RW_ATTR(tpl, "status", PropertyGetter, PropertySetter);
  RW_ATTR(tpl, "type", PropertyGetter, PropertySetter);
  RW_ATTR(tpl, "connection", PropertyGetter, PropertySetter);
  RW_ATTR(tpl, "minscaledenom", PropertyGetter, PropertySetter);
  RW_ATTR(tpl, "maxscaledenom", PropertyGetter, PropertySetter);
  RW_ATTR(tpl, "projection", PropertyGetter, PropertySetter);
  RW_ATTR(tpl, "units", PropertyGetter, PropertySetter);
  RO_ATTR(tpl, "connectiontype", PropertyGetter);
  RO_ATTR(tpl, "metadata", PropertyGetter);

  target->Set(Nan::New("Layer").ToLocalChecked(), tpl->GetFunction());
  constructor.Reset(tpl);
}

MSLayer::MSLayer(layerObj *layer) : ObjectWrap(), this_(layer) {}

MSLayer::MSLayer() : ObjectWrap(), this_(0) {}

MSLayer::~MSLayer() { }

NAN_METHOD(MSLayer::New)
{
  MSLayer* obj;
  if (!info.IsConstructCall()) {
    Nan::ThrowError("Cannot call constructor as function, you need to use 'new' keyword");
    return;
  }

  if (info[0]->IsExternal()) {
    v8::Local<v8::External> ext = info[0].As<v8::External>();
    void *ptr = ext->Value();
    MSLayer *f =  static_cast<MSLayer *>(ptr);
    f->Wrap(info.This());
    info.GetReturnValue().Set(info.This());
    return;
  }

  if (info.Length() != 1 || !info[0]->IsString()) {
    Nan::ThrowTypeError("requires one argument: a string");
    return;
  }

  layerObj* layer = (layerObj*)calloc(1,sizeof(layerObj));
  initLayer(layer, (mapObj*)NULL);

  layer->name = strdup(TOSTR(info[0]));

  obj = new MSLayer(layer);
  obj->Wrap(info.This());
  info.GetReturnValue().Set(info.This());
}

v8::Local<v8::Value> MSLayer::NewInstance(layerObj *ptr) {
  Nan::EscapableHandleScope scope;
  MSLayer* obj = new MSLayer();
  obj->this_ = ptr;
  v8::Local<v8::Value> ext = Nan::New<v8::External>(obj);
  return scope.Escape(Nan::New(constructor)->GetFunction()->NewInstance(1, &ext));
}

NAN_GETTER(MSLayer::PropertyGetter) {

  MSLayer *obj = Nan::ObjectWrap::Unwrap<MSLayer>(info.Holder());

  if (STRCMP(property, "name")) {
    info.GetReturnValue().Set(Nan::New(obj->this_->name).ToLocalChecked());
  } else if (STRCMP(property, "status")) {
    info.GetReturnValue().Set(obj->this_->status);
  } else if (STRCMP(property, "metadata")) {
    info.GetReturnValue().Set(MSHashTable::NewInstance(&(obj->this_->metadata)));
  } else if (STRCMP(property, "type")) {
    info.GetReturnValue().Set(obj->this_->type);
  } else if (STRCMP(property, "minscaledenom")) {
    info.GetReturnValue().Set(obj->this_->minscaledenom);
  } else if (STRCMP(property, "maxscaledenom")) {
    info.GetReturnValue().Set(obj->this_->maxscaledenom);
  } else if (STRCMP(property, "units")) {
    info.GetReturnValue().Set(obj->this_->units);
  } else if (STRCMP(property, "projection")) {
    info.GetReturnValue().Set(MSProjection::NewInstance(&obj->this_->projection));
  } else if (STRCMP(property, "connection")) {
    if (obj->this_->connection == NULL) {
      info.GetReturnValue().Set(Nan::Undefined());
    } else {
      info.GetReturnValue().Set(Nan::New(obj->this_->connection).ToLocalChecked());
    }
  } else if (STRCMP(property, "connectiontype")) {
    info.GetReturnValue().Set(obj->this_->connectiontype);
  }
}

NAN_SETTER(MSLayer::PropertySetter) {
  MSLayer *obj = Nan::ObjectWrap::Unwrap<MSLayer>(info.Holder());

  if (STRCMP(property, "name")) {
    REPLACE_STRING(obj->this_->name, value)
  } else if (STRCMP(property, "status")) {
    obj->this_->status = value->NumberValue();
  } else if (STRCMP(property, "minscaledenom")) {
    obj->this_->minscaledenom = value->NumberValue();
  } else if (STRCMP(property, "maxscaledenom")) {
    obj->this_->maxscaledenom = value->NumberValue();
  } else if (STRCMP(property, "units")) {
    int32_t units = value->Int32Value();
    if (units >= MS_INCHES && units <= MS_NAUTICALMILES) {
      obj->this_->units = (MS_UNITS) units;
    }
  } else if (STRCMP(property, "projection")) {
    msLoadProjectionString(&(obj->this_->projection), TOSTR(value));
  } else if (STRCMP(property, "type")) {
    int32_t type = value->Int32Value();
    if (type >= MS_LAYER_ANNOTATION && type <= MS_LAYER_TILEINDEX) {
      obj->this_->type = (MS_LAYER_TYPE) type;
    }
  } else if (STRCMP(property, "connection")) {
    REPLACE_STRING(obj->this_->connection, value)
  }
}

NAN_METHOD(MSLayer::GetGridIntersectionCoordinates) {
  MSLayer *obj = Nan::ObjectWrap::Unwrap<MSLayer>(info.This());

  int i = 0;

  graticuleIntersectionObj *values = msGraticuleLayerGetIntersectionPoints(obj->this_->map, obj->this_);

  v8::Local<v8::Array> left = Nan::New<v8::Array>(values->nLeft);
  v8::Local<v8::Array> top = Nan::New<v8::Array>(values->nTop);
  v8::Local<v8::Array> right = Nan::New<v8::Array>(values->nRight);
  v8::Local<v8::Array> bottom = Nan::New<v8::Array>(values->nBottom);
  v8::Local<v8::Object> val;

  for (i=0; i<values->nLeft; i++) {
    val = Nan::New<v8::Object>();
    val->Set(Nan::New("x").ToLocalChecked(), Nan::New(values->pasLeft[i].x));
    val->Set(Nan::New("y").ToLocalChecked(), Nan::New(values->pasLeft[i].y));
    val->Set(Nan::New("label").ToLocalChecked(), Nan::New(values->papszLeftLabels[i]).ToLocalChecked());
    left->Set(i, val);
  }
  for (i=0; i<values->nTop; i++) {
    val = Nan::New<v8::Object>();
    val->Set(Nan::New("x").ToLocalChecked(), Nan::New(values->pasTop[i].x));
    val->Set(Nan::New("y").ToLocalChecked(), Nan::New(values->pasTop[i].y));
    val->Set(Nan::New("label").ToLocalChecked(), Nan::New(values->papszTopLabels[i]).ToLocalChecked());
    top->Set(i, val);
  }
  for (i=0; i<values->nRight; i++) {
    val = Nan::New<v8::Object>();
    val->Set(Nan::New("x").ToLocalChecked(), Nan::New(values->pasRight[i].x));
    val->Set(Nan::New("y").ToLocalChecked(), Nan::New(values->pasRight[i].y));
    val->Set(Nan::New("label").ToLocalChecked(), Nan::New(values->papszRightLabels[i]).ToLocalChecked());
    right->Set(i, val);
  }
  for (i=0; i<values->nBottom; i++) {
    val = Nan::New<v8::Object>();
    val->Set(Nan::New("x").ToLocalChecked(), Nan::New(values->pasBottom[i].x));
    val->Set(Nan::New("y").ToLocalChecked(), Nan::New(values->pasBottom[i].y));
    val->Set(Nan::New("label").ToLocalChecked(), Nan::New(values->papszBottomLabels[i]).ToLocalChecked());
    bottom->Set(i, val);
  }

  // return object like this:
  // {
  //   left: [{position: 0, label: '123.00'}],
  //   top: [{position: 0, label: '123.00'}],
  //   right: [{position: 0, label: '123.00'}],
  //   bottom: [{position: 0, label: '123.00'}],
  // }
  v8::Local<v8::Object> result = Nan::New<v8::Object>();
  result->Set(Nan::New("left").ToLocalChecked(), left);
  result->Set(Nan::New("top").ToLocalChecked(), top);
  result->Set(Nan::New("right").ToLocalChecked(), right);
  result->Set(Nan::New("bottom").ToLocalChecked(), bottom);
  info.GetReturnValue().Set(result);
}

NAN_METHOD(MSLayer::UpdateFromString) {
  MSLayer *obj = Nan::ObjectWrap::Unwrap<MSLayer>(info.This());
  int result;
  if (info.Length() < 1) {
    Nan::ThrowError("UpdateFromString requires one string argument");
    return;
  }
  if (!info[0]->IsString()) {
    Nan::ThrowError("UpdateFromString requires one string argument");
    return;
  }
  result = msUpdateLayerFromString(obj->this_, TOSTR(info[0]), MS_FALSE);
  info.GetReturnValue().Set(result);
}

#if MS_VERSION_NUM >= 60400
NAN_METHOD(MSLayer::ToString) {
  MSLayer *obj = Nan::ObjectWrap::Unwrap<MSLayer>(info.This());
  char *text = msWriteLayerToString(obj->this_);
  info.GetReturnValue().Set(Nan::New(text).ToLocalChecked());
}
#endif
<|endoftext|>


<commit_before>/*
 The MIT License (MIT)

 Copyright (c) [2016] [BTC.COM]

 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
 in the Software without restriction, including without limitation the rights
 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 copies of the Software, and to permit persons to whom the Software is
 furnished to do so, subject to the following conditions:

 The above copyright notice and this permission notice shall be included in
 all copies or substantial portions of the Software.

 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 THE SOFTWARE.
 */
#include "BlockMakerEth.h"
#include "EthConsensus.h"

#include "utilities_js.hpp"

#include <boost/thread.hpp>

////////////////////////////////////////////////BlockMakerEth////////////////////////////////////////////////////////////////
BlockMakerEth::BlockMakerEth(const BlockMakerDefinition& def, const char *kafkaBrokers, const MysqlConnectInfo &poolDB)
  : BlockMaker(def, kafkaBrokers, poolDB)
{
  useSubmitBlockDetail_ = checkRpcSubmitBlockDetail();
  if (useSubmitBlockDetail_) {
    LOG(INFO) << "use RPC eth_submitBlockDetail";
  }
  else if (checkRpcSubmitBlock()) {
    LOG(INFO) << "use RPC eth_submitBlock, it has limited functionality and the block hash will not be recorded.";
  }
  else {
    LOG(FATAL) << "Ethereum nodes doesn't support both eth_submitBlockDetail and eth_submitBlock, cannot submit block!";
  }
}

void BlockMakerEth::processSolvedShare(rd_kafka_message_t *rkmessage)
{
  const char *message = (const char *)rkmessage->payload;
  JsonNode r;
  if (!JsonNode::parse(message, message + rkmessage->len, r))
  {
    LOG(ERROR) << "decode common event failure";
    return;
  }

  if (r.type() != Utilities::JS::type::Obj ||
      r["nonce"].type() != Utilities::JS::type::Str ||
      r["header"].type() != Utilities::JS::type::Str ||
      r["mix"].type() != Utilities::JS::type::Str ||
      r["height"].type() != Utilities::JS::type::Int ||
      r["networkDiff"].type() != Utilities::JS::type::Int ||
      r["userId"].type() != Utilities::JS::type::Int ||
      r["workerId"].type() != Utilities::JS::type::Int ||
      r["workerFullName"].type() != Utilities::JS::type::Str ||
      r["chain"].type() != Utilities::JS::type::Str)
  {
    LOG(ERROR) << "eth solved share format wrong";
    return;
  }

  StratumWorker worker;
  worker.userId_ = r["userId"].int32();
  worker.workerHashId_ = r["workerId"].int64();
  worker.fullName_ = r["workerFullName"].str();

  submitBlockNonBlocking(r["nonce"].str(), r["header"].str(), r["mix"].str(), def_.nodes,
                         r["height"].uint32(), r["chain"].str(), r["networkDiff"].uint64(),
                         worker);
}

bool BlockMakerEth::submitBlock(const string &nonce, const string &header, const string &mix,
                                const string &rpcUrl, const string &rpcUserPass) {
  string request = Strings::Format("{\"jsonrpc\": \"2.0\", \"method\": \"eth_submitWork\", \"params\": [\"%s\",\"%s\",\"%s\"], \"id\": 5}\n",
                                   HexAddPrefix(nonce).c_str(),
                                   HexAddPrefix(header).c_str(),
                                   HexAddPrefix(mix).c_str());

  string response;
  bool ok = blockchainNodeRpcCall(rpcUrl.c_str(), rpcUserPass.c_str(), request.c_str(), response);
  DLOG(INFO) << "eth_submitWork request: " << request;
  DLOG(INFO) << "eth_submitWork response: " << response;
  if (!ok) {
    LOG(WARNING) << "Call RPC eth_submitWork failed, node url: " << rpcUrl;
    return false;
  }

  JsonNode r;
  if (!JsonNode::parse(response.c_str(), response.c_str() + response.size(), r)) {
    LOG(WARNING) << "decode response failure, node url: " << rpcUrl << ", response: " << response;
    return false;
  }

  if (r.type() != Utilities::JS::type::Obj || r["result"].type() != Utilities::JS::type::Bool) {
    LOG(WARNING) << "node doesn't support eth_submitWork, node url: " << rpcUrl << ", response: " << response;
    return false;
  }

  return r["result"].boolean();
}

/**
  * RPC eth_submitWorkDetail:
  *     A new RPC to submit POW work to Ethereum node. It has the same functionality as `eth_submitWork`
  *     but returns more details about the submitted block.
  *     It defined by the BTCPool project and implemented in the Parity Ethereum node as a patch.
  *
  * Params (same as `eth_submitWork`):
  *     [
  *         (string) nonce,
  *         (string) pow_hash,
  *         (string) mix_hash
  *     ]
  *
  * Result:
  *     [
  *         (bool)           success,
  *         (string or null) error_msg,
  *         (string or null) block_hash,
  *         ... // more fields may added in the future
  *     ]
  */
bool BlockMakerEth::submitBlockDetail(const string &nonce, const string &header, const string &mix,
                                      const string &rpcUrl, const string &rpcUserPass,
                                      string &errMsg, string &blockHash) {

  string request = Strings::Format("{\"jsonrpc\": \"2.0\", \"method\": \"eth_submitWorkDetail\", \"params\": [\"%s\",\"%s\",\"%s\"], \"id\": 5}\n",
                                   HexAddPrefix(nonce).c_str(),
                                   HexAddPrefix(header).c_str(),
                                   HexAddPrefix(mix).c_str());

  string response;
  bool ok = blockchainNodeRpcCall(rpcUrl.c_str(), rpcUserPass.c_str(), request.c_str(), response);
  DLOG(INFO) << "eth_submitWorkDetail request: " << request;
  DLOG(INFO) << "eth_submitWorkDetail response: " << response;
  if (!ok) {
    LOG(WARNING) << "Call RPC eth_submitWorkDetail failed, node url: " << rpcUrl;
    return false;
  }

  JsonNode r;
  if (!JsonNode::parse(response.c_str(), response.c_str() + response.size(), r)) {
    LOG(WARNING) << "decode response failure, node url: " << rpcUrl << ", response: " << response;
    return false;
  }

  if (r.type() != Utilities::JS::type::Obj || r["result"].type() != Utilities::JS::type::Array) {
    LOG(WARNING) << "node doesn't support eth_submitWorkDetail, node url: " << rpcUrl << ", response: " << response;
    return false;
  }

  auto result = r["result"].children();

  bool success = false;
  if (result->size() >= 1 && result->at(0).type() == Utilities::JS::type::Bool) {
    success = result->at(0).boolean();
  }

  if (result->size() >= 2 && result->at(1).type() == Utilities::JS::type::Str) {
    errMsg = result->at(1).str();
  }

  if (result->size() >= 3 && result->at(2).type() == Utilities::JS::type::Str) {
    blockHash = result->at(2).str();
  }

  return success;
}

bool BlockMakerEth::checkRpcSubmitBlock() {
  string request = Strings::Format("{\"jsonrpc\": \"2.0\", \"method\": \"eth_submitWork\", \"params\": [\"%s\",\"%s\",\"%s\"], \"id\": 5}\n",
                                   "0x0000000000000000",
                                   "0x0000000000000000000000000000000000000000000000000000000000000000",
                                   "0x0000000000000000000000000000000000000000000000000000000000000000");

  for (const auto &itr : nodeRpcUri_) {
    string response;
    bool ok = blockchainNodeRpcCall(itr.first.c_str(), itr.second.c_str(), request.c_str(), response);
    if (!ok) {
      LOG(WARNING) << "Call RPC eth_submitWork failed, node url: " << itr.first;
      return false;
    }

    JsonNode r;
    if (!JsonNode::parse(response.c_str(), response.c_str() + response.size(), r)) {
      LOG(WARNING) << "decode response failure, node url: " << itr.first << ", response: " << response;
      return false;
    }

    if (r.type() != Utilities::JS::type::Obj || r["result"].type() != Utilities::JS::type::Bool) {
      LOG(WARNING) << "node doesn't support eth_submitWork, node url: " << itr.first << ", response: " << response;
      return false;
    }
  }

  return true;
}

bool BlockMakerEth::checkRpcSubmitBlockDetail() {
  string request = Strings::Format("{\"jsonrpc\": \"2.0\", \"method\": \"eth_submitWorkDetail\", \"params\": [\"%s\",\"%s\",\"%s\"], \"id\": 5}\n",
                                   "0x0000000000000000",
                                   "0x0000000000000000000000000000000000000000000000000000000000000000",
                                   "0x0000000000000000000000000000000000000000000000000000000000000000");

  for (const auto &itr : nodeRpcUri_) {
    string response;
    bool ok = blockchainNodeRpcCall(itr.first.c_str(), itr.second.c_str(), request.c_str(), response);
    if (!ok) {
      LOG(WARNING) << "Call RPC eth_submitWorkDetail failed, node url: " << itr.first;
      return false;
    }

    JsonNode r;
    if (!JsonNode::parse(response.c_str(), response.c_str() + response.size(), r)) {
      LOG(WARNING) << "decode response failure, node url: " << itr.first << ", response: " << response;
      return false;
    }

    if (r.type() != Utilities::JS::type::Obj ||
      r["result"].type() != Utilities::JS::type::Array ||
      r["result"].children()->size() < 3 ||
      r["result"].children()->at(0).type() != Utilities::JS::type::Bool)
    {
      LOG(WARNING) << "node doesn't support eth_submitWorkDetail, node url: " << itr.first << ", response: " << response;
      return false;
    }
  }

  return true;
}

void BlockMakerEth::submitBlockNonBlocking(const string &nonce, const string &header, const string &mix, const vector<NodeDefinition> &nodes,
                                           const uint32_t height, const string &chain, const uint64_t networkDiff, const StratumWorker &worker) {
  boost::thread t(boost::bind(&BlockMakerEth::_submitBlockThread, this,
                              nonce, header, mix, nodes,
                              height, chain, networkDiff, worker));
}

void BlockMakerEth::_submitBlockThread(const string &nonce, const string &header, const string &mix, const vector<NodeDefinition> &nodes,
                                       const uint32_t height, const string &chain, const uint64_t networkDiff, const StratumWorker &worker) {
  string blockHash;

  auto submitBlockOnce = [&]() {
    // try eth_submitWorkDetail
    if (useSubmitBlockDetail_) {
      for (size_t i=0; i<nodes.size(); i++) {
        string errMsg;
        auto node = nodes[i];
        bool success = submitBlockDetail(nonce, header, mix, node.rpcAddr_, node.rpcUserPwd_,
                                        errMsg, blockHash);
        if (success) {
          LOG(INFO) << "eth_submitWorkDetail success, chain: " << chain << ", height: " << height << ", hash: " << blockHash
                    << ", networkDiff: " << networkDiff << ", worker: " << worker.fullName_;
          return true;
        }

        LOG(WARNING) << "eth_submitWorkDetail failed, chain: " << chain << ", height: " << height << ", hash_no_nonce: " << header
                    << ", err_msg: " << errMsg;
      }
    }

    // try eth_submitWork
    {
      for (size_t i=0; i<nodes.size(); i++) {
        auto node = nodes[i];
        bool success = submitBlock(nonce, header, mix, node.rpcAddr_, node.rpcUserPwd_);
        if (success) {
          LOG(INFO) << "eth_submitWork success, chain: " << chain << ", height: " << height << ", hash_no_nonce: " << header
                    << ", networkDiff: " << networkDiff << ", worker: " << worker.fullName_;
          return true;
        }

        LOG(WARNING) << "eth_submitWork failed, chain: " << chain << ", height: " << height << ", hash_no_nonce: " << header;
      }
    }

    return false;
  };

  int retryTime = 5;
  while (retryTime > 0) {
    if (submitBlockOnce()) {
      break;
    }
    sleep(6 - retryTime); // first sleep 1s, second sleep 2s, ...
    retryTime--;
  }

  // Still writing to the database even if submitting failed
  saveBlockToDB(header, blockHash, height, chain, networkDiff, worker);
}

void BlockMakerEth::saveBlockToDB(const string &header, const string &blockHash, const uint32_t height,
                                  const string &chain, const uint64_t networkDiff, const StratumWorker &worker) {
  const string nowStr = date("%F %T");
  string sql;
  sql = Strings::Format("INSERT INTO `found_blocks` "
                        " (`puid`, `worker_id`"
                        ", `worker_full_name`, `chain`"
                        ", `height`, `hash`, `hash_no_nonce`"
                        ", `rewards`"
                        ", `network_diff`, `created_at`)"
                        " VALUES (%ld, %" PRId64
                        ", '%s', '%s'"
                        ", %lu, '%s', '%s'"
                        ", %" PRId64
                        ", %" PRIu64 ", '%s'); ",
                        worker.userId_, worker.workerHashId_,
                        // filter again, just in case
                        filterWorkerName(worker.fullName_).c_str(), chain.c_str(),
                        height, blockHash.c_str(), header.c_str(),
                        EthConsensus::getStaticBlockReward(height, chain),
                        networkDiff, nowStr.c_str());

  // try connect to DB
  MySQLConnection db(poolDB_);
  for (size_t i = 0; i < 3; i++) {
    if (db.ping())
      break;
    else
      sleep(3);
  }

  if (db.execute(sql) == false) {
    LOG(ERROR) << "insert found block failure: " << sql;
  }
  else
  {
    LOG(INFO) << "insert found block success for height " << height;
  }
}
<commit_msg>blkmaker ETH: don't allow empty node list.<commit_after>/*
 The MIT License (MIT)

 Copyright (c) [2016] [BTC.COM]

 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
 in the Software without restriction, including without limitation the rights
 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 copies of the Software, and to permit persons to whom the Software is
 furnished to do so, subject to the following conditions:

 The above copyright notice and this permission notice shall be included in
 all copies or substantial portions of the Software.

 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 THE SOFTWARE.
 */
#include "BlockMakerEth.h"
#include "EthConsensus.h"

#include "utilities_js.hpp"

#include <boost/thread.hpp>

////////////////////////////////////////////////BlockMakerEth////////////////////////////////////////////////////////////////
BlockMakerEth::BlockMakerEth(const BlockMakerDefinition& def, const char *kafkaBrokers, const MysqlConnectInfo &poolDB)
  : BlockMaker(def, kafkaBrokers, poolDB)
{
  useSubmitBlockDetail_ = checkRpcSubmitBlockDetail();
  if (useSubmitBlockDetail_) {
    LOG(INFO) << "use RPC eth_submitBlockDetail";
  }
  else if (checkRpcSubmitBlock()) {
    LOG(INFO) << "use RPC eth_submitBlock, it has limited functionality and the block hash will not be recorded.";
  }
  else {
    LOG(FATAL) << "Ethereum nodes doesn't support both eth_submitBlockDetail and eth_submitBlock, cannot submit block!";
  }
}

void BlockMakerEth::processSolvedShare(rd_kafka_message_t *rkmessage)
{
  const char *message = (const char *)rkmessage->payload;
  JsonNode r;
  if (!JsonNode::parse(message, message + rkmessage->len, r))
  {
    LOG(ERROR) << "decode common event failure";
    return;
  }

  if (r.type() != Utilities::JS::type::Obj ||
      r["nonce"].type() != Utilities::JS::type::Str ||
      r["header"].type() != Utilities::JS::type::Str ||
      r["mix"].type() != Utilities::JS::type::Str ||
      r["height"].type() != Utilities::JS::type::Int ||
      r["networkDiff"].type() != Utilities::JS::type::Int ||
      r["userId"].type() != Utilities::JS::type::Int ||
      r["workerId"].type() != Utilities::JS::type::Int ||
      r["workerFullName"].type() != Utilities::JS::type::Str ||
      r["chain"].type() != Utilities::JS::type::Str)
  {
    LOG(ERROR) << "eth solved share format wrong";
    return;
  }

  StratumWorker worker;
  worker.userId_ = r["userId"].int32();
  worker.workerHashId_ = r["workerId"].int64();
  worker.fullName_ = r["workerFullName"].str();

  submitBlockNonBlocking(r["nonce"].str(), r["header"].str(), r["mix"].str(), def_.nodes,
                         r["height"].uint32(), r["chain"].str(), r["networkDiff"].uint64(),
                         worker);
}

bool BlockMakerEth::submitBlock(const string &nonce, const string &header, const string &mix,
                                const string &rpcUrl, const string &rpcUserPass) {
  string request = Strings::Format("{\"jsonrpc\": \"2.0\", \"method\": \"eth_submitWork\", \"params\": [\"%s\",\"%s\",\"%s\"], \"id\": 5}\n",
                                   HexAddPrefix(nonce).c_str(),
                                   HexAddPrefix(header).c_str(),
                                   HexAddPrefix(mix).c_str());

  string response;
  bool ok = blockchainNodeRpcCall(rpcUrl.c_str(), rpcUserPass.c_str(), request.c_str(), response);
  DLOG(INFO) << "eth_submitWork request: " << request;
  DLOG(INFO) << "eth_submitWork response: " << response;
  if (!ok) {
    LOG(WARNING) << "Call RPC eth_submitWork failed, node url: " << rpcUrl;
    return false;
  }

  JsonNode r;
  if (!JsonNode::parse(response.c_str(), response.c_str() + response.size(), r)) {
    LOG(WARNING) << "decode response failure, node url: " << rpcUrl << ", response: " << response;
    return false;
  }

  if (r.type() != Utilities::JS::type::Obj || r["result"].type() != Utilities::JS::type::Bool) {
    LOG(WARNING) << "node doesn't support eth_submitWork, node url: " << rpcUrl << ", response: " << response;
    return false;
  }

  return r["result"].boolean();
}

/**
  * RPC eth_submitWorkDetail:
  *     A new RPC to submit POW work to Ethereum node. It has the same functionality as `eth_submitWork`
  *     but returns more details about the submitted block.
  *     It defined by the BTCPool project and implemented in the Parity Ethereum node as a patch.
  *
  * Params (same as `eth_submitWork`):
  *     [
  *         (string) nonce,
  *         (string) pow_hash,
  *         (string) mix_hash
  *     ]
  *
  * Result:
  *     [
  *         (bool)           success,
  *         (string or null) error_msg,
  *         (string or null) block_hash,
  *         ... // more fields may added in the future
  *     ]
  */
bool BlockMakerEth::submitBlockDetail(const string &nonce, const string &header, const string &mix,
                                      const string &rpcUrl, const string &rpcUserPass,
                                      string &errMsg, string &blockHash) {

  string request = Strings::Format("{\"jsonrpc\": \"2.0\", \"method\": \"eth_submitWorkDetail\", \"params\": [\"%s\",\"%s\",\"%s\"], \"id\": 5}\n",
                                   HexAddPrefix(nonce).c_str(),
                                   HexAddPrefix(header).c_str(),
                                   HexAddPrefix(mix).c_str());

  string response;
  bool ok = blockchainNodeRpcCall(rpcUrl.c_str(), rpcUserPass.c_str(), request.c_str(), response);
  DLOG(INFO) << "eth_submitWorkDetail request: " << request;
  DLOG(INFO) << "eth_submitWorkDetail response: " << response;
  if (!ok) {
    LOG(WARNING) << "Call RPC eth_submitWorkDetail failed, node url: " << rpcUrl;
    return false;
  }

  JsonNode r;
  if (!JsonNode::parse(response.c_str(), response.c_str() + response.size(), r)) {
    LOG(WARNING) << "decode response failure, node url: " << rpcUrl << ", response: " << response;
    return false;
  }

  if (r.type() != Utilities::JS::type::Obj || r["result"].type() != Utilities::JS::type::Array) {
    LOG(WARNING) << "node doesn't support eth_submitWorkDetail, node url: " << rpcUrl << ", response: " << response;
    return false;
  }

  auto result = r["result"].children();

  bool success = false;
  if (result->size() >= 1 && result->at(0).type() == Utilities::JS::type::Bool) {
    success = result->at(0).boolean();
  }

  if (result->size() >= 2 && result->at(1).type() == Utilities::JS::type::Str) {
    errMsg = result->at(1).str();
  }

  if (result->size() >= 3 && result->at(2).type() == Utilities::JS::type::Str) {
    blockHash = result->at(2).str();
  }

  return success;
}

bool BlockMakerEth::checkRpcSubmitBlock() {
  string request = Strings::Format("{\"jsonrpc\": \"2.0\", \"method\": \"eth_submitWork\", \"params\": [\"%s\",\"%s\",\"%s\"], \"id\": 5}\n",
                                   "0x0000000000000000",
                                   "0x0000000000000000000000000000000000000000000000000000000000000000",
                                   "0x0000000000000000000000000000000000000000000000000000000000000000");

  for (const auto &itr : nodeRpcUri_) {
    string response;
    bool ok = blockchainNodeRpcCall(itr.first.c_str(), itr.second.c_str(), request.c_str(), response);
    if (!ok) {
      LOG(WARNING) << "Call RPC eth_submitWork failed, node url: " << itr.first;
      return false;
    }

    JsonNode r;
    if (!JsonNode::parse(response.c_str(), response.c_str() + response.size(), r)) {
      LOG(WARNING) << "decode response failure, node url: " << itr.first << ", response: " << response;
      return false;
    }

    if (r.type() != Utilities::JS::type::Obj || r["result"].type() != Utilities::JS::type::Bool) {
      LOG(WARNING) << "node doesn't support eth_submitWork, node url: " << itr.first << ", response: " << response;
      return false;
    }
  }

  return true;
}

bool BlockMakerEth::checkRpcSubmitBlockDetail() {
  string request = Strings::Format("{\"jsonrpc\": \"2.0\", \"method\": \"eth_submitWorkDetail\", \"params\": [\"%s\",\"%s\",\"%s\"], \"id\": 5}\n",
                                   "0x0000000000000000",
                                   "0x0000000000000000000000000000000000000000000000000000000000000000",
                                   "0x0000000000000000000000000000000000000000000000000000000000000000");

  if (nodeRpcUri_.empty()) {
    LOG(FATAL) << "Node list is empty, cannot submit block!";
    return false;
  }

  for (const auto &itr : nodeRpcUri_) {
    string response;
    bool ok = blockchainNodeRpcCall(itr.first.c_str(), itr.second.c_str(), request.c_str(), response);
    if (!ok) {
      LOG(WARNING) << "Call RPC eth_submitWorkDetail failed, node url: " << itr.first;
      return false;
    }

    JsonNode r;
    if (!JsonNode::parse(response.c_str(), response.c_str() + response.size(), r)) {
      LOG(WARNING) << "decode response failure, node url: " << itr.first << ", response: " << response;
      return false;
    }

    if (r.type() != Utilities::JS::type::Obj ||
      r["result"].type() != Utilities::JS::type::Array ||
      r["result"].children()->size() < 3 ||
      r["result"].children()->at(0).type() != Utilities::JS::type::Bool)
    {
      LOG(WARNING) << "node doesn't support eth_submitWorkDetail, node url: " << itr.first << ", response: " << response;
      return false;
    }
  }

  return true;
}

void BlockMakerEth::submitBlockNonBlocking(const string &nonce, const string &header, const string &mix, const vector<NodeDefinition> &nodes,
                                           const uint32_t height, const string &chain, const uint64_t networkDiff, const StratumWorker &worker) {
  boost::thread t(boost::bind(&BlockMakerEth::_submitBlockThread, this,
                              nonce, header, mix, nodes,
                              height, chain, networkDiff, worker));
}

void BlockMakerEth::_submitBlockThread(const string &nonce, const string &header, const string &mix, const vector<NodeDefinition> &nodes,
                                       const uint32_t height, const string &chain, const uint64_t networkDiff, const StratumWorker &worker) {
  string blockHash;

  auto submitBlockOnce = [&]() {
    // try eth_submitWorkDetail
    if (useSubmitBlockDetail_) {
      for (size_t i=0; i<nodes.size(); i++) {
        string errMsg;
        auto node = nodes[i];
        bool success = submitBlockDetail(nonce, header, mix, node.rpcAddr_, node.rpcUserPwd_,
                                        errMsg, blockHash);
        if (success) {
          LOG(INFO) << "eth_submitWorkDetail success, chain: " << chain << ", height: " << height << ", hash: " << blockHash
                    << ", networkDiff: " << networkDiff << ", worker: " << worker.fullName_;
          return true;
        }

        LOG(WARNING) << "eth_submitWorkDetail failed, chain: " << chain << ", height: " << height << ", hash_no_nonce: " << header
                    << ", err_msg: " << errMsg;
      }
    }

    // try eth_submitWork
    {
      for (size_t i=0; i<nodes.size(); i++) {
        auto node = nodes[i];
        bool success = submitBlock(nonce, header, mix, node.rpcAddr_, node.rpcUserPwd_);
        if (success) {
          LOG(INFO) << "eth_submitWork success, chain: " << chain << ", height: " << height << ", hash_no_nonce: " << header
                    << ", networkDiff: " << networkDiff << ", worker: " << worker.fullName_;
          return true;
        }

        LOG(WARNING) << "eth_submitWork failed, chain: " << chain << ", height: " << height << ", hash_no_nonce: " << header;
      }
    }

    return false;
  };

  int retryTime = 5;
  while (retryTime > 0) {
    if (submitBlockOnce()) {
      break;
    }
    sleep(6 - retryTime); // first sleep 1s, second sleep 2s, ...
    retryTime--;
  }

  // Still writing to the database even if submitting failed
  saveBlockToDB(header, blockHash, height, chain, networkDiff, worker);
}

void BlockMakerEth::saveBlockToDB(const string &header, const string &blockHash, const uint32_t height,
                                  const string &chain, const uint64_t networkDiff, const StratumWorker &worker) {
  const string nowStr = date("%F %T");
  string sql;
  sql = Strings::Format("INSERT INTO `found_blocks` "
                        " (`puid`, `worker_id`"
                        ", `worker_full_name`, `chain`"
                        ", `height`, `hash`, `hash_no_nonce`"
                        ", `rewards`"
                        ", `network_diff`, `created_at`)"
                        " VALUES (%ld, %" PRId64
                        ", '%s', '%s'"
                        ", %lu, '%s', '%s'"
                        ", %" PRId64
                        ", %" PRIu64 ", '%s'); ",
                        worker.userId_, worker.workerHashId_,
                        // filter again, just in case
                        filterWorkerName(worker.fullName_).c_str(), chain.c_str(),
                        height, blockHash.c_str(), header.c_str(),
                        EthConsensus::getStaticBlockReward(height, chain),
                        networkDiff, nowStr.c_str());

  // try connect to DB
  MySQLConnection db(poolDB_);
  for (size_t i = 0; i < 3; i++) {
    if (db.ping())
      break;
    else
      sleep(3);
  }

  if (db.execute(sql) == false) {
    LOG(ERROR) << "insert found block failure: " << sql;
  }
  else
  {
    LOG(INFO) << "insert found block success for height " << height;
  }
}
<|endoftext|>


<commit_before>// Minimal teleportation OpenQASM example
// Source: ./examples/qasm/qasm_teleport_minimal.cpp
#include <iostream>

#include "qpp.h"

int main() {
    using namespace qpp;

    // create a qpp::QCircuit from a QASM file
    QCircuit qc = qasm::read_from_file(QPP_ROOT_DIR
                                       "/examples/qasm/teleport_minimal.qasm");

    // we could have also used a C++ standard stream from <fstream>, like below
    // std::ifstream ifs{PATH "/examples/qasm/teleport_minimal.qasm"};
    // QCircuit qc = qasm::read(ifs);

    // note that QASM measurements are non-destructive, so the final state after
    // this step when executed on an engine will be a state of 3 qubits; that is
    // why we discard the first two qubits in the next line
    qc.discard({0, 1});

    std::cout << ">> BEGIN CIRCUIT\n";
    // display the circuit; use qc.to_JSON() for JSON output
    std::cout << qc << '\n';
    std::cout << ">> END CIRCUIT\n\n";

    QEngine q_engine{qc}; // create an engine out of a quantum circuit
    q_engine.execute();   // execute the circuit
    std::cout << ">> BEGIN ENGINE STATISTICS\n";
    // display the measurement statistics; use q_engine.to_JSON() for JSON
    // output
    std::cout << q_engine << '\n';
    std::cout << ">> END ENGINE STATISTICS\n\n";

    // displays the final output state
    std::cout << ">> Final state:\n";
    std::cout << disp(q_engine.get_psi()) << '\n';
}
<commit_msg>Update qasm_teleport_minimal.cpp<commit_after>// Minimal teleportation OpenQASM example
// Source: ./examples/qasm/qasm_teleport_minimal.cpp
#include <iostream>

#include "qpp.h"

int main() {
    using namespace qpp;

    // create a qpp::QCircuit from a QASM file
    QCircuit qc = qasm::read_from_file(QPP_ROOT_DIR
                                       "/examples/qasm/teleport_minimal.qasm");

    // we could have also used a C++ standard stream from <fstream>, like below
    // std::ifstream ifs{PATH "/examples/qasm/teleport_minimal.qasm"};
    // QCircuit qc = qasm::read(ifs);

    // note that QASM measurements are non-destructive, so the final state after
    // this step when executed on an engine will be a state of 3 qubits; that is
    // why we discard the first two qubits in the next line
    qc.discard({0, 1});

    // display the quantum circuit and its corresponding resources
    // use qc.to_JSON() for JSON output
    std::cout << qc << "\n\n" << qc.get_resources() << "\n\n";

    QEngine q_engine{qc}; // create an engine out of a quantum circuit

    // execute the quantum circuit
    q_engine.execute();

    // display the measurement statistics
    // use q_engine.to_JSON() for JSON output
    std::cout << q_engine << '\n';

    // displays the final output state
    std::cout << ">> Final state:\n";
    std::cout << disp(q_engine.get_psi()) << '\n';
}
<|endoftext|>


<commit_before><commit_msg>paintitems.cc: fixed arrow color by using foreground().<commit_after><|endoftext|>


<commit_before>// RUN: %clang_cc1 -fsyntax-only -verify %s
template<typename T>
struct X0 {
  typedef T* type;

  void f0(T);
  void f1(type);
};

template<> void X0<char>::f0(char);
template<> void X0<char>::f1(type);

namespace PR6161 {
  template<typename _CharT>
  class numpunct : public locale::facet // expected-error{{use of undeclared identifier 'locale'}} \
              // expected-error{{expected class name}}
  {
    static locale::id id; // expected-error{{use of undeclared identifier}}
  };
  numpunct<char>::~numpunct(); // expected-error{{expected the class name after '~' to name a destructor}}
}
<commit_msg>Add regression test for PR12331.<commit_after>// RUN: %clang_cc1 -fsyntax-only -verify %s
template<typename T>
struct X0 {
  typedef T* type;

  void f0(T);
  void f1(type);
};

template<> void X0<char>::f0(char);
template<> void X0<char>::f1(type);

namespace PR6161 {
  template<typename _CharT>
  class numpunct : public locale::facet // expected-error{{use of undeclared identifier 'locale'}} \
              // expected-error{{expected class name}}
  {
    static locale::id id; // expected-error{{use of undeclared identifier}}
  };
  numpunct<char>::~numpunct(); // expected-error{{expected the class name after '~' to name a destructor}}
}

namespace PR12331 {
  template<typename T> struct S {
    struct U { static const int n = 5; };
    enum E { e = U::n }; // expected-note {{implicit instantiation first required here}}
    int arr[e];
  };
  template<> struct S<int>::U { static const int n = sizeof(int); }; // expected-error {{explicit specialization of 'U' after instantiation}}
}
<|endoftext|>


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

#include "protocol.h"

#include "util.h"
#include "utilstrencodings.h"

#ifndef WIN32
# include <arpa/inet.h>
#endif

namespace NetMsgType {
    const char *VERSION="version";
    const char *VERACK="verack";
    const char *ADDR="addr";
    const char *INV="inv";
    const char *GETDATA="getdata";
    const char *MERKLEBLOCK="merkleblock";
    const char *GETBLOCKS="getblocks";
    const char *GETHEADERS="getheaders";
    const char *TX="tx";
    const char *HEADERS="headers";
    const char *BLOCK="block";
    const char *GETADDR="getaddr";
    const char *MEMPOOL="mempool";
    const char *PING="ping";
    const char *PONG="pong";
    const char *NOTFOUND="notfound";
    const char *FILTERLOAD="filterload";
    const char *FILTERADD="filteradd";
    const char *FILTERCLEAR="filterclear";
    const char *REJECT="reject";
    const char *SENDHEADERS="sendheaders";
    const char *FEEFILTER="feefilter";
    const char *SENDCMPCT="sendcmpct";
    const char *CMPCTBLOCK="cmpctblock";
    const char *GETBLOCKTXN="getblocktxn";
    const char *BLOCKTXN="blocktxn";
    const char *DANDELIONTX="dandeliontx";
//znode
    const char *TXLOCKVOTE="txlvote";
    const char *SPORK="spork";
    const char *GETSPORKS="getsporks";
    const char *ZNODEPAYMENTVOTE="mnw";
    const char *ZNODEPAYMENTBLOCK="mnwb";
    const char *ZNODEPAYMENTSYNC="mnget";
    const char *MNANNOUNCE="mnb";
    const char *MNPING="mnp";
    const char *DSACCEPT="dsa";
    const char *DSVIN="dsi";
    const char *DSFINALTX="dsf";
    const char *DSSIGNFINALTX="dss";
    const char *DSCOMPLETE="dsc";
    const char *DSSTATUSUPDATE="dssu";
    const char *DSTX="dstx";
    const char *DSQUEUE="dsq";
    const char *DSEG="dseg";
    const char *SYNCSTATUSCOUNT="ssc";
    const char *MNVERIFY="mnv";
    const char *TXLOCKREQUEST="ix";
    const char *MNGOVERNANCESYNC="govsync";
    const char *MNGOVERNANCEOBJECT="govobj";
    const char *MNGOVERNANCEOBJECTVOTE="govobjvote";
    const char *GETMNLISTDIFF="getmnlistd";
    const char *MNLISTDIFF="mnlistdiff";
    const char *QSENDRECSIGS="qsendrecsigs";
    const char *QFCOMMITMENT="qfcommit";
    const char *QCONTRIB="qcontrib";
    const char *QCOMPLAINT="qcomplaint";
    const char *QJUSTIFICATION="qjustify";
    const char *QPCOMMITMENT="qpcommit";
    const char *QWATCH="qwatch";
    const char *QSIGSESANN="qsigsesann";
    const char *QSIGSHARESINV="qsigsinv";
    const char *QGETSIGSHARES="qgetsigs";
    const char *QBSIGSHARES="qbsigs";
    const char *QSIGREC="qsigrec";
    const char *CLSIG="clsig";
    const char *ISLOCK="islock";
    const char *MNAUTH="mnauth";
};

/** All known message types. Keep this in the same order as the list of
 * messages above and in protocol.h.
 */
const static std::string allNetMessageTypes[] = {
    NetMsgType::VERSION,
    NetMsgType::VERACK,
    NetMsgType::ADDR,
    NetMsgType::INV,
    NetMsgType::GETDATA,
    NetMsgType::MERKLEBLOCK,
    NetMsgType::GETBLOCKS,
    NetMsgType::GETHEADERS,
    NetMsgType::TX,
    NetMsgType::HEADERS,
    NetMsgType::BLOCK,
    NetMsgType::GETADDR,
    NetMsgType::MEMPOOL,
    NetMsgType::PING,
    NetMsgType::PONG,
    NetMsgType::NOTFOUND,
    NetMsgType::FILTERLOAD,
    NetMsgType::FILTERADD,
    NetMsgType::FILTERCLEAR,
    NetMsgType::REJECT,
    NetMsgType::SENDHEADERS,
    NetMsgType::FEEFILTER,
    NetMsgType::SENDCMPCT,
    NetMsgType::CMPCTBLOCK,
    NetMsgType::GETBLOCKTXN,
    NetMsgType::BLOCKTXN,
    NetMsgType::DANDELIONTX,
    //znode
    NetMsgType::TXLOCKREQUEST,
    NetMsgType::TXLOCKVOTE,
    NetMsgType::ZNODEPAYMENTVOTE,
    NetMsgType::ZNODEPAYMENTBLOCK,
    NetMsgType::ZNODEPAYMENTSYNC,
    NetMsgType::SPORK,
    NetMsgType::GETSPORKS,
    NetMsgType::MNANNOUNCE,
    NetMsgType::MNPING,
    NetMsgType::GETMNLISTDIFF,
    NetMsgType::MNLISTDIFF,
    NetMsgType::SYNCSTATUSCOUNT,
    NetMsgType::MNVERIFY,
    NetMsgType::QSENDRECSIGS,
    NetMsgType::QFCOMMITMENT,
    NetMsgType::QCONTRIB,
    NetMsgType::QCOMPLAINT,
    NetMsgType::QJUSTIFICATION,
    NetMsgType::QPCOMMITMENT,
    NetMsgType::QWATCH,
    NetMsgType::QSIGSESANN,
    NetMsgType::QSIGSHARESINV,
    NetMsgType::QGETSIGSHARES,
    NetMsgType::QBSIGSHARES,
    NetMsgType::QSIGREC,
    NetMsgType::CLSIG,
    NetMsgType::ISLOCK,
    NetMsgType::MNAUTH,
};
const static std::vector<std::string> allNetMessageTypesVec(allNetMessageTypes, allNetMessageTypes+ARRAYLEN(allNetMessageTypes));

CMessageHeader::CMessageHeader(const MessageStartChars& pchMessageStartIn)
{
    memcpy(pchMessageStart, pchMessageStartIn, MESSAGE_START_SIZE);
    memset(pchCommand, 0, sizeof(pchCommand));
    nMessageSize = -1;
    memset(pchChecksum, 0, CHECKSUM_SIZE);
}

CMessageHeader::CMessageHeader(const MessageStartChars& pchMessageStartIn, const char* pszCommand, unsigned int nMessageSizeIn)
{
    memcpy(pchMessageStart, pchMessageStartIn, MESSAGE_START_SIZE);
    memset(pchCommand, 0, sizeof(pchCommand));
    strncpy(pchCommand, pszCommand, COMMAND_SIZE);
    nMessageSize = nMessageSizeIn;
    memset(pchChecksum, 0, CHECKSUM_SIZE);
}

std::string CMessageHeader::GetCommand() const
{
    return std::string(pchCommand, pchCommand + strnlen(pchCommand, COMMAND_SIZE));
}

bool CMessageHeader::IsValid(const MessageStartChars& pchMessageStartIn) const
{
    // Check start string
    if (memcmp(pchMessageStart, pchMessageStartIn, MESSAGE_START_SIZE) != 0)
        return false;

    // Check the command string for errors
    for (const char* p1 = pchCommand; p1 < pchCommand + COMMAND_SIZE; p1++)
    {
        if (*p1 == 0)
        {
            // Must be all zeros after the first zero
            for (; p1 < pchCommand + COMMAND_SIZE; p1++)
                if (*p1 != 0)
                    return false;
        }
        else if (*p1 < ' ' || *p1 > 0x7E)
            return false;
    }

    // Message size
    if (nMessageSize > MAX_SIZE)
    {
        LogPrintf("CMessageHeader::IsValid(): (%s, %u bytes) nMessageSize > MAX_SIZE\n", GetCommand(), nMessageSize);
        return false;
    }

    return true;
}

CAddress::CAddress() : CService()
{
    Init();
}

CAddress::CAddress(CService ipIn, ServiceFlags nServicesIn) : CService(ipIn)
{
    Init();
    nServices = nServicesIn;
}

void CAddress::Init()
{
    nServices = NODE_NONE;
    nTime = 100000000;
}

CInv::CInv()
{
    type = 0;
    hash.SetNull();
}

CInv::CInv(int typeIn, const uint256& hashIn)
{
    type = typeIn;
    hash = hashIn;
}

bool operator<(const CInv& a, const CInv& b)
{
    return (a.type < b.type || (a.type == b.type && a.hash < b.hash));
}

std::string CInv::GetCommand() const
{
    std::string cmd;
    if (type & MSG_WITNESS_FLAG)
        cmd.append("witness-");
    int masked = type & MSG_TYPE_MASK;
    // TODO: switch(masked)
    switch (type)
    {
    case MSG_TX:             return cmd.append(NetMsgType::TX);
    case MSG_BLOCK:          return cmd.append(NetMsgType::BLOCK);
    case MSG_FILTERED_BLOCK: return cmd.append(NetMsgType::MERKLEBLOCK);
    case MSG_CMPCT_BLOCK:    return cmd.append(NetMsgType::CMPCTBLOCK);
    case MSG_DANDELION_TX:   return cmd.append(NetMsgType::DANDELIONTX);

    case MSG_TXLOCK_REQUEST:        return cmd.append(NetMsgType::TXLOCKREQUEST);
    case MSG_TXLOCK_VOTE:           return cmd.append(NetMsgType::TXLOCKVOTE);
    case MSG_SPORK:                 return cmd.append(NetMsgType::SPORK);
    case MSG_ZNODE_PAYMENT_VOTE:    return cmd.append(NetMsgType::ZNODEPAYMENTVOTE);
    case MSG_ZNODE_PAYMENT_BLOCK:   return cmd.append(NetMsgType::ZNODEPAYMENTBLOCK);
    case MSG_ZNODE_ANNOUNCE:        return cmd.append(NetMsgType::MNANNOUNCE);
    case MSG_ZNODE_PING:            return cmd.append(NetMsgType::MNPING);
    case MSG_DSTX:                  return cmd.append(NetMsgType::DSTX);
    case MSG_ZNODE_VERIFY:          return cmd.append(NetMsgType::MNVERIFY);
    default:
        throw std::out_of_range(strprintf("CInv::GetCommand(): type=%d unknown type", type));
    }
}

std::string CInv::ToString() const
{
    try {
        return strprintf("%s %s", GetCommand(), hash.ToString());
    } catch(const std::out_of_range &) {
        return strprintf("0x%08x %s", type, hash.ToString());
    }
}

const std::vector<std::string> &getAllNetMessageTypes()
{
    return allNetMessageTypesVec;
}
<commit_msg>Added znode evo command network names<commit_after>// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2016 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "protocol.h"

#include "util.h"
#include "utilstrencodings.h"

#ifndef WIN32
# include <arpa/inet.h>
#endif

namespace NetMsgType {
    const char *VERSION="version";
    const char *VERACK="verack";
    const char *ADDR="addr";
    const char *INV="inv";
    const char *GETDATA="getdata";
    const char *MERKLEBLOCK="merkleblock";
    const char *GETBLOCKS="getblocks";
    const char *GETHEADERS="getheaders";
    const char *TX="tx";
    const char *HEADERS="headers";
    const char *BLOCK="block";
    const char *GETADDR="getaddr";
    const char *MEMPOOL="mempool";
    const char *PING="ping";
    const char *PONG="pong";
    const char *NOTFOUND="notfound";
    const char *FILTERLOAD="filterload";
    const char *FILTERADD="filteradd";
    const char *FILTERCLEAR="filterclear";
    const char *REJECT="reject";
    const char *SENDHEADERS="sendheaders";
    const char *FEEFILTER="feefilter";
    const char *SENDCMPCT="sendcmpct";
    const char *CMPCTBLOCK="cmpctblock";
    const char *GETBLOCKTXN="getblocktxn";
    const char *BLOCKTXN="blocktxn";
    const char *DANDELIONTX="dandeliontx";
//znode
    const char *TXLOCKVOTE="txlvote";
    const char *SPORK="spork";
    const char *GETSPORKS="getsporks";
    const char *ZNODEPAYMENTVOTE="mnw";
    const char *ZNODEPAYMENTBLOCK="mnwb";
    const char *ZNODEPAYMENTSYNC="mnget";
    const char *MNANNOUNCE="mnb";
    const char *MNPING="mnp";
    const char *DSACCEPT="dsa";
    const char *DSVIN="dsi";
    const char *DSFINALTX="dsf";
    const char *DSSIGNFINALTX="dss";
    const char *DSCOMPLETE="dsc";
    const char *DSSTATUSUPDATE="dssu";
    const char *DSTX="dstx";
    const char *DSQUEUE="dsq";
    const char *DSEG="dseg";
    const char *SYNCSTATUSCOUNT="ssc";
    const char *MNVERIFY="mnv";
    const char *TXLOCKREQUEST="ix";
    const char *MNGOVERNANCESYNC="govsync";
    const char *MNGOVERNANCEOBJECT="govobj";
    const char *MNGOVERNANCEOBJECTVOTE="govobjvote";
    const char *GETMNLISTDIFF="getmnlistd";
    const char *MNLISTDIFF="mnlistdiff";
    const char *QSENDRECSIGS="qsendrecsigs";
    const char *QFCOMMITMENT="qfcommit";
    const char *QCONTRIB="qcontrib";
    const char *QCOMPLAINT="qcomplaint";
    const char *QJUSTIFICATION="qjustify";
    const char *QPCOMMITMENT="qpcommit";
    const char *QWATCH="qwatch";
    const char *QSIGSESANN="qsigsesann";
    const char *QSIGSHARESINV="qsigsinv";
    const char *QGETSIGSHARES="qgetsigs";
    const char *QBSIGSHARES="qbsigs";
    const char *QSIGREC="qsigrec";
    const char *CLSIG="clsig";
    const char *ISLOCK="islock";
    const char *MNAUTH="mnauth";
};

/** All known message types. Keep this in the same order as the list of
 * messages above and in protocol.h.
 */
const static std::string allNetMessageTypes[] = {
    NetMsgType::VERSION,
    NetMsgType::VERACK,
    NetMsgType::ADDR,
    NetMsgType::INV,
    NetMsgType::GETDATA,
    NetMsgType::MERKLEBLOCK,
    NetMsgType::GETBLOCKS,
    NetMsgType::GETHEADERS,
    NetMsgType::TX,
    NetMsgType::HEADERS,
    NetMsgType::BLOCK,
    NetMsgType::GETADDR,
    NetMsgType::MEMPOOL,
    NetMsgType::PING,
    NetMsgType::PONG,
    NetMsgType::NOTFOUND,
    NetMsgType::FILTERLOAD,
    NetMsgType::FILTERADD,
    NetMsgType::FILTERCLEAR,
    NetMsgType::REJECT,
    NetMsgType::SENDHEADERS,
    NetMsgType::FEEFILTER,
    NetMsgType::SENDCMPCT,
    NetMsgType::CMPCTBLOCK,
    NetMsgType::GETBLOCKTXN,
    NetMsgType::BLOCKTXN,
    NetMsgType::DANDELIONTX,
    //znode
    NetMsgType::TXLOCKREQUEST,
    NetMsgType::TXLOCKVOTE,
    NetMsgType::ZNODEPAYMENTVOTE,
    NetMsgType::ZNODEPAYMENTBLOCK,
    NetMsgType::ZNODEPAYMENTSYNC,
    NetMsgType::SPORK,
    NetMsgType::GETSPORKS,
    NetMsgType::MNANNOUNCE,
    NetMsgType::MNPING,
    NetMsgType::GETMNLISTDIFF,
    NetMsgType::MNLISTDIFF,
    NetMsgType::SYNCSTATUSCOUNT,
    NetMsgType::MNVERIFY,
    NetMsgType::QSENDRECSIGS,
    NetMsgType::QFCOMMITMENT,
    NetMsgType::QCONTRIB,
    NetMsgType::QCOMPLAINT,
    NetMsgType::QJUSTIFICATION,
    NetMsgType::QPCOMMITMENT,
    NetMsgType::QWATCH,
    NetMsgType::QSIGSESANN,
    NetMsgType::QSIGSHARESINV,
    NetMsgType::QGETSIGSHARES,
    NetMsgType::QBSIGSHARES,
    NetMsgType::QSIGREC,
    NetMsgType::CLSIG,
    NetMsgType::ISLOCK,
    NetMsgType::MNAUTH,
};
const static std::vector<std::string> allNetMessageTypesVec(allNetMessageTypes, allNetMessageTypes+ARRAYLEN(allNetMessageTypes));

CMessageHeader::CMessageHeader(const MessageStartChars& pchMessageStartIn)
{
    memcpy(pchMessageStart, pchMessageStartIn, MESSAGE_START_SIZE);
    memset(pchCommand, 0, sizeof(pchCommand));
    nMessageSize = -1;
    memset(pchChecksum, 0, CHECKSUM_SIZE);
}

CMessageHeader::CMessageHeader(const MessageStartChars& pchMessageStartIn, const char* pszCommand, unsigned int nMessageSizeIn)
{
    memcpy(pchMessageStart, pchMessageStartIn, MESSAGE_START_SIZE);
    memset(pchCommand, 0, sizeof(pchCommand));
    strncpy(pchCommand, pszCommand, COMMAND_SIZE);
    nMessageSize = nMessageSizeIn;
    memset(pchChecksum, 0, CHECKSUM_SIZE);
}

std::string CMessageHeader::GetCommand() const
{
    return std::string(pchCommand, pchCommand + strnlen(pchCommand, COMMAND_SIZE));
}

bool CMessageHeader::IsValid(const MessageStartChars& pchMessageStartIn) const
{
    // Check start string
    if (memcmp(pchMessageStart, pchMessageStartIn, MESSAGE_START_SIZE) != 0)
        return false;

    // Check the command string for errors
    for (const char* p1 = pchCommand; p1 < pchCommand + COMMAND_SIZE; p1++)
    {
        if (*p1 == 0)
        {
            // Must be all zeros after the first zero
            for (; p1 < pchCommand + COMMAND_SIZE; p1++)
                if (*p1 != 0)
                    return false;
        }
        else if (*p1 < ' ' || *p1 > 0x7E)
            return false;
    }

    // Message size
    if (nMessageSize > MAX_SIZE)
    {
        LogPrintf("CMessageHeader::IsValid(): (%s, %u bytes) nMessageSize > MAX_SIZE\n", GetCommand(), nMessageSize);
        return false;
    }

    return true;
}

CAddress::CAddress() : CService()
{
    Init();
}

CAddress::CAddress(CService ipIn, ServiceFlags nServicesIn) : CService(ipIn)
{
    Init();
    nServices = nServicesIn;
}

void CAddress::Init()
{
    nServices = NODE_NONE;
    nTime = 100000000;
}

CInv::CInv()
{
    type = 0;
    hash.SetNull();
}

CInv::CInv(int typeIn, const uint256& hashIn)
{
    type = typeIn;
    hash = hashIn;
}

bool operator<(const CInv& a, const CInv& b)
{
    return (a.type < b.type || (a.type == b.type && a.hash < b.hash));
}

std::string CInv::GetCommand() const
{
    std::string cmd;
    if (type & MSG_WITNESS_FLAG)
        cmd.append("witness-");
    int masked = type & MSG_TYPE_MASK;
    // TODO: switch(masked)
    switch (type)
    {
    case MSG_TX:             return cmd.append(NetMsgType::TX);
    case MSG_BLOCK:          return cmd.append(NetMsgType::BLOCK);
    case MSG_FILTERED_BLOCK: return cmd.append(NetMsgType::MERKLEBLOCK);
    case MSG_CMPCT_BLOCK:    return cmd.append(NetMsgType::CMPCTBLOCK);
    case MSG_DANDELION_TX:   return cmd.append(NetMsgType::DANDELIONTX);

    case MSG_TXLOCK_REQUEST:        return cmd.append(NetMsgType::TXLOCKREQUEST);
    case MSG_TXLOCK_VOTE:           return cmd.append(NetMsgType::TXLOCKVOTE);
    case MSG_SPORK:                 return cmd.append(NetMsgType::SPORK);
    case MSG_ZNODE_PAYMENT_VOTE:    return cmd.append(NetMsgType::ZNODEPAYMENTVOTE);
    case MSG_ZNODE_PAYMENT_BLOCK:   return cmd.append(NetMsgType::ZNODEPAYMENTBLOCK);
    case MSG_ZNODE_ANNOUNCE:        return cmd.append(NetMsgType::MNANNOUNCE);
    case MSG_ZNODE_PING:            return cmd.append(NetMsgType::MNPING);
    case MSG_DSTX:                  return cmd.append(NetMsgType::DSTX);
    case MSG_ZNODE_VERIFY:          return cmd.append(NetMsgType::MNVERIFY);

    case MSG_QUORUM_FINAL_COMMITMENT:       return cmd.append(NetMsgType::QFCOMMITMENT);
    case MSG_QUORUM_CONTRIB:                return cmd.append(NetMsgType::QCONTRIB);
    case MSG_QUORUM_COMPLAINT:              return cmd.append(NetMsgType::QCOMPLAINT);
    case MSG_QUORUM_JUSTIFICATION:          return cmd.append(NetMsgType::QJUSTIFICATION);
    case MSG_QUORUM_PREMATURE_COMMITMENT:   return cmd.append(NetMsgType::QPCOMMITMENT);
    case MSG_QUORUM_RECOVERED_SIG:          return cmd.append(NetMsgType::QSIGREC);
    case MSG_CLSIG:                         return cmd.append(NetMsgType::CLSIG);
    case MSG_ISLOCK:                        return cmd.append(NetMsgType::ISLOCK);
    default:
        throw std::out_of_range(strprintf("CInv::GetCommand(): type=%d unknown type", type));
    }
}

std::string CInv::ToString() const
{
    try {
        return strprintf("%s %s", GetCommand(), hash.ToString());
    } catch(const std::out_of_range &) {
        return strprintf("0x%08x %s", type, hash.ToString());
    }
}

const std::vector<std::string> &getAllNetMessageTypes()
{
    return allNetMessageTypesVec;
}
<|endoftext|>