Skip to content

Commit

Permalink
Better separation between V8 and non-V8 filter code.
Browse files Browse the repository at this point in the history
Better separation between Windows and Linux filter code.
  • Loading branch information
ztarem committed Nov 15, 2018
1 parent 93dca0f commit 1805405
Show file tree
Hide file tree
Showing 18 changed files with 1,330 additions and 103 deletions.
10 changes: 10 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -121,8 +121,18 @@ test_filters.sh

/doc/doxygen/

# V8
v8build

# Eclipse CDT
.autotools
.cproject
.project
.settings/

# Qt Creator
*.user
*.config
*.creator
*.files
*.includes
33 changes: 23 additions & 10 deletions src/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ LIBBITCOIN_MULTICHAIN=multichain/libbitcoin_multichain.a
LIBBITCOIN_UNIVALUE=univalue/libbitcoin_univalue.a
LIBBITCOINQT=qt/libbitcoinqt.a
LIBSECP256K1=secp256k1/libsecp256k1.la
if !TARGET_WINDOWS
LIBBITCOIN_V8=libbitcoin_v8.a
endif

$(LIBSECP256K1): $(wildcard secp256k1/src/*) $(wildcard secp256k1/include/*)
$(AM_V_at)$(MAKE) $(AM_MAKEFLAGS) -C $(@D) $(@F)
Expand All @@ -52,7 +55,9 @@ if ENABLE_WALLET
BITCOIN_INCLUDES += $(BDB_CPPFLAGS)
EXTRA_LIBRARIES += libbitcoin_wallet.a
endif

if !TARGET_WINDOWS
EXTRA_LIBRARIES += $(LIBBITCOIN_V8)
endif
if BUILD_BITCOIN_LIBS
lib_LTLIBRARIES = libbitcoinconsensus.la
LIBBITCOIN_CONSENSUS=libbitcoinconsensus.la
Expand Down Expand Up @@ -168,12 +173,6 @@ obj/build.h: FORCE
$(abs_top_srcdir)
libbitcoin_util_a-clientversion.$(OBJEXT): obj/build.h

V8_SOURCES = \
v8/v8engine.cpp \
v8/v8filter.cpp \
v8/callbacks.cpp \
v8/v8utils.cpp

# server: shared between bitcoind and bitcoin-qt
libbitcoin_server_a_CPPFLAGS = $(BITCOIN_INCLUDES) $(MINIUPNPC_CPPFLAGS)
libbitcoin_server_a_SOURCES = \
Expand Down Expand Up @@ -431,6 +430,18 @@ V8_LIBS = \
-licui18n \
-lrt -ldl

libbitcoin_v8_a_SOURCES = \
v8/v8engine.cpp \
v8/v8filter.cpp \
v8/callbacks.cpp \
v8/v8json_spirit.cpp

#if TARGET_WINDOWS
libbitcoin_v8_a_SOURCES += v8/callbacks_win.cpp v8/v8blob.dpp
#endif

libbitcoin_v8_a_CPPFLAGS = $(BITCOIN_INCLUDES) $(V8_INCLUDE)

# multichaind binary #
multichaind_LDADD = \
$(LIBBITCOIN_SERVER) \
Expand All @@ -445,6 +456,10 @@ multichaind_LDADD = \
$(LIBMEMENV) \
$(LIBSECP256K1)

if !TARGET_WINDOWS
multichaind_LDADD += $(LIBBITCOIN_V8)
endif

#if ENABLE_WALLET
#multichaind_LDADD += libbitcoin_wallet.a
#endif
Expand All @@ -454,9 +469,7 @@ multichaind_SOURCES = \
chainparams/buildgenesis.cpp \
filters/filter.cpp \
filters/filtercallback.cpp \
filters/watchdog.cpp \
$(V8_SOURCES)
#
filters/watchdog.cpp

if TARGET_WINDOWS
multichaind_SOURCES += multichaind-res.rc
Expand Down
17 changes: 12 additions & 5 deletions src/filters/filtercallback.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ static std::map<std::string, rpcfn_type> FilterCallbackFunctions{
CALLBACK_LOOKUP(verifymessage)
};

#ifdef WIN32
void FilterCallback::UbjCallback(const char *name, const unsigned char *args, unsigned char **result, int *resultSize)
//#ifdef WIN32
void FilterCallback::UbjCallback(const char *name, const unsigned char *args, unsigned char **result, size_t *resultSize)
{
int err;
Array jspArgs = ubjson_read(args, 1, MAX_DEPTH, &err).get_array();
Expand All @@ -43,9 +43,16 @@ void FilterCallback::UbjCallback(const char *name, const unsigned char *args, un
mc_Script script;
script.AddElement();
ubjson_write(jspResult, &script, MAX_DEPTH);
script.GetRawData(result, resultSize);
unsigned char *result_;
int resultSize_;
if (script.GetRawData(&result_, &resultSize_) == MC_ERR_NOERROR)
{
*resultSize = static_cast<size_t>(resultSize_);
*result = new unsigned char[*resultSize];
memcpy(*result, result_, *resultSize);
}
}
#else
//#else
void FilterCallback::JspCallback(string name, Array args, Value &result)
{
result = Value::null;
Expand All @@ -63,7 +70,7 @@ void FilterCallback::JspCallback(string name, Array args, Value &result)
this->CreateCallbackLogError(name, args, e);
}
}
#endif // WIN32
//#endif // WIN32

void FilterCallback::CreateCallbackLog(string name, Array args, Value result)
{
Expand Down
8 changes: 4 additions & 4 deletions src/filters/filtercallback.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,11 @@ class FilterCallback : public IFilterCallback
m_callbackLog.clear();
}

#ifdef WIN32
void UbjCallback(const char *name, const unsigned char *args, unsigned char **result, int *resultSize) override;
#else
//#ifdef WIN32
void UbjCallback(const char *name, const unsigned char *args, unsigned char **result, size_t *resultSize) override;
//#else
void JspCallback(std::string name, json_spirit::Array args, json_spirit::Value &result) override;
#endif // WIN32
//#endif // WIN32

private:
json_spirit::Array m_callbackLog;
Expand Down
8 changes: 4 additions & 4 deletions src/filters/ifiltercallback.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@
class IFilterCallback
{
public:
#ifdef WIN32
virtual void UbjCallback(const char *name, const unsigned char *args, unsigned char **result, int *resultSize) = 0;
#else
//#ifdef WIN32
virtual void UbjCallback(const char *name, const unsigned char *args, unsigned char **result, size_t *resultSize) = 0;
//#else
virtual void JspCallback(std::string name, json_spirit::Array args, json_spirit::Value &result) = 0;
#endif // WIN32
//#endif // WIN32

virtual ~IFilterCallback()
{
Expand Down
4 changes: 1 addition & 3 deletions src/v8/callbacks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,8 @@
// MultiChain code distributed under the GPLv3 license, see COPYING file.

#include "v8/callbacks.h"
#include "rpc/rpcprotocol.h"
#include "rpc/rpcserver.h"
#include "utils/util.h"
#include "v8/v8engine.h"
#include "v8/v8json_spirit.h"
#include "v8/v8utils.h"
#include <cassert>

Expand Down
99 changes: 99 additions & 0 deletions src/v8/callbacks_win.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
// Copyright (c) 2014-2018 Coin Sciences Ltd
// MultiChain code distributed under the GPLv3 license, see COPYING file.

#include "v8/callbacks.h"
#include "v8/v8engine.h"
#include "v8/v8utils.h"
#include "v8/v8ubjson.h"
#include "v8/v8blob.h"
#include <cassert>

namespace mc_v8
{
/**
* Call an RPC function from a V8 JS callback.
*
* Marshal the arguments and the return value between V8 and json_spirit using intermediate JSON strings.
* Optionally filter the result before returning it to JS.
*
* @param name The name of the RPC function.
* @param args The V8 arguments/return value.
*/
void CallRpcFunction(std::string name, const v8::FunctionCallbackInfo<v8::Value> &args)
{
v8::Isolate *isolate = args.GetIsolate();
v8::Locker locker(isolate);
v8::Isolate::Scope isolateScope(isolate);
v8::HandleScope handleScope(isolate);
v8::Local<v8::Context> context(isolate->GetCurrentContext());
v8::Context::Scope contextScope(context);

IFilterCallback *filterCallback = static_cast<IFilterCallback *>(args.Data().As<v8::External>()->Value());

auto v8args = v8::Array::New(isolate, args.Length());
for (int i = 0; i < args.Length(); ++i)
{
v8args->Set(static_cast<unsigned>(i), args[i]);
}

BlobPtr argsBlob = Blob::Instance("args");
BlobPtr resultBlob = Blob::Instance("result");
V82Ubj(isolate, v8args, argsBlob);
unsigned char *result;
size_t resultSize;

filterCallback->UbjCallback(name.c_str(), argsBlob->Data(), &result, &resultSize);
resultBlob->Set(result, resultSize);

if (resultBlob->IsEmpty())
{
args.GetReturnValue().SetUndefined();
}
else
{
int err;
args.GetReturnValue().Set(Ubj2V8(isolate, resultBlob, &err));
}

if (result != nullptr)
{
delete [] result;
}
}

// clang-format off
#define FILTER_FUNCTION(name) \
void filter_##name(const v8::FunctionCallbackInfo<v8::Value> &args) \
{ \
CallRpcFunction(#name, args); \
}

FILTER_FUNCTION(getfiltertxid)
FILTER_FUNCTION(getfiltertransaction)
FILTER_FUNCTION(getfilterstreamitem)
FILTER_FUNCTION(getfilterassetbalances)
FILTER_FUNCTION(setfilterparam)
FILTER_FUNCTION(getfiltertxinput)
FILTER_FUNCTION(getlastblockinfo)
FILTER_FUNCTION(getassetinfo)
FILTER_FUNCTION(getstreaminfo)
FILTER_FUNCTION(verifypermission)
FILTER_FUNCTION(verifymessage)

#define FILTER_LOOKUP(name) { #name, filter_##name }

std::map<std::string, v8::FunctionCallback> callbackLookup{
FILTER_LOOKUP(getfiltertxid),
FILTER_LOOKUP(getfiltertransaction),
FILTER_LOOKUP(getfilterstreamitem),
FILTER_LOOKUP(getfilterassetbalances),
FILTER_LOOKUP(setfilterparam),
FILTER_LOOKUP(getfiltertxinput),
FILTER_LOOKUP(getlastblockinfo),
FILTER_LOOKUP(getassetinfo),
FILTER_LOOKUP(getstreaminfo),
FILTER_LOOKUP(verifypermission),
FILTER_LOOKUP(verifymessage)
};
// clang-format on
} // namespace mc_v8
64 changes: 64 additions & 0 deletions src/v8/v8blob.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
#include "v8blob.h"
#include <cstring>

namespace mc_v8
{
BlobPtr Blob::Instance(std::string name)
{
auto it = m_instances.find(name);
if (it == m_instances.end())
{
it = m_instances.insert(std::make_pair(name, std::make_shared<Blob>())).first;
}
return it->second;
}

Blob::~Blob()
{
if (m_buffer != nullptr)
{
delete[] m_buffer;
}
}

void Blob::Reset()
{
m_size = 0;
}

void Blob::Set(void *data, size_t size)
{
this->Reset();
this->Append(data, size);
}

void Blob::Append(void *data, size_t size)
{
this->Resize(size);
std::memcpy(m_buffer + m_size, data, size);
m_size += size;
}

void Blob::Remove(std::string name)
{
m_instances.equal_range(name);
}

void Blob::Resize(size_t add_size)
{
if (m_size + add_size > m_allocated)
{
size_t new_size = ((m_size + add_size - 1) / size_increment + 1) * size_increment;
auto new_buffer = new unsigned char[new_size];
if (m_allocated > 0)
{
std::memcpy(new_buffer, m_buffer, m_allocated);
delete[] m_buffer;
}
m_buffer = new_buffer;
m_allocated = new_size;
}
}

std::map<std::string, BlobPtr> Blob::m_instances;
} // namespace mc_v8
Loading

0 comments on commit 1805405

Please sign in to comment.