<commit_before>// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "config.h"
#include "bindings/core/v8/PrivateScriptRunner.h"

#include "bindings/core/v8/DOMWrapperWorld.h"
#include "bindings/core/v8/ExceptionState.h"
#include "bindings/core/v8/V8Binding.h"
#include "bindings/core/v8/V8PerContextData.h"
#include "bindings/core/v8/V8ScriptRunner.h"
#include "core/PrivateScriptSources.h"
#ifndef NDEBUG
#include "core/PrivateScriptSourcesForTesting.h"
#endif
#include "core/dom/ExceptionCode.h"

namespace blink {

static v8::Handle<v8::Value> compilePrivateScript(v8::Isolate* isolate, String className)
{
    size_t index;
#ifndef NDEBUG
    for (index = 0; index < WTF_ARRAY_LENGTH(kPrivateScriptSourcesForTesting); index++) {
        if (className == kPrivateScriptSourcesForTesting[index].name)
            break;
    }
    if (index != WTF_ARRAY_LENGTH(kPrivateScriptSourcesForTesting)) {
        String source(reinterpret_cast<const char*>(kPrivateScriptSourcesForTesting[index].source), kPrivateScriptSourcesForTesting[index].size);
        return V8ScriptRunner::compileAndRunInternalScript(v8String(isolate, source), isolate);
    }
#endif

    // |kPrivateScriptSources| is defined in V8PrivateScriptSources.h, which is auto-generated
    // by make_private_script.py.
    for (index = 0; index < WTF_ARRAY_LENGTH(kPrivateScriptSources); index++) {
        if (className == kPrivateScriptSources[index].name)
            break;
    }
    if (index == WTF_ARRAY_LENGTH(kPrivateScriptSources)) {
        WTF_LOG_ERROR("Private script error: Target source code was not found. (Class name = %s)\n", className.utf8().data());
        RELEASE_ASSERT_NOT_REACHED();
    }

    v8::TryCatch block;
    String source(reinterpret_cast<const char*>(kPrivateScriptSources[index].source), kPrivateScriptSources[index].size);
    v8::Handle<v8::Value> result = V8ScriptRunner::compileAndRunInternalScript(v8String(isolate, source), isolate);
    if (block.HasCaught()) {
        WTF_LOG_ERROR("Private script error: Compile failed. (Class name = %s)\n", className.utf8().data());
        if (!block.Message().IsEmpty())
            WTF_LOG_ERROR("%s\n", toCoreString(block.Message()->Get()).utf8().data());
        RELEASE_ASSERT_NOT_REACHED();
    }
    return result;
}

static v8::Handle<v8::Object> classObjectOfPrivateScript(ScriptState* scriptState, String className)
{
    ASSERT(scriptState->perContextData());
    ASSERT(scriptState->executionContext());
    v8::Isolate* isolate = scriptState->isolate();
    v8::Handle<v8::Value> compiledClass = scriptState->perContextData()->compiledPrivateScript(className);
    if (compiledClass.IsEmpty()) {
        v8::Handle<v8::Value> installedClasses = scriptState->perContextData()->compiledPrivateScript("PrivateScriptRunner");
        if (installedClasses.IsEmpty()) {
            installedClasses = compilePrivateScript(isolate, "PrivateScriptRunner");
            scriptState->perContextData()->setCompiledPrivateScript("PrivateScriptRunner", installedClasses);
        }
        RELEASE_ASSERT(!installedClasses.IsEmpty());
        RELEASE_ASSERT(installedClasses->IsObject());

        compilePrivateScript(isolate, className);
        compiledClass = v8::Handle<v8::Object>::Cast(installedClasses)->Get(v8String(isolate, className));
        RELEASE_ASSERT(!compiledClass.IsEmpty());
        RELEASE_ASSERT(compiledClass->IsObject());
        scriptState->perContextData()->setCompiledPrivateScript(className, compiledClass);
    }
    return v8::Handle<v8::Object>::Cast(compiledClass);
}

static void initializeHolderIfNeeded(ScriptState* scriptState, v8::Handle<v8::Object> classObject, v8::Handle<v8::Value> holder)
{
    RELEASE_ASSERT(!holder.IsEmpty());
    RELEASE_ASSERT(holder->IsObject());
    v8::Handle<v8::Object> holderObject = v8::Handle<v8::Object>::Cast(holder);
    v8::Isolate* isolate = scriptState->isolate();
    v8::Handle<v8::Value> isInitialized = V8HiddenValue::getHiddenValue(isolate, holderObject, V8HiddenValue::privateScriptObjectIsInitialized(isolate));
    if (isInitialized.IsEmpty()) {
        v8::TryCatch block;
        v8::Handle<v8::Value> initializeFunction = classObject->Get(v8String(isolate, "initialize"));
        if (!initializeFunction.IsEmpty() && initializeFunction->IsFunction()) {
            v8::TryCatch block;
            V8ScriptRunner::callFunction(v8::Handle<v8::Function>::Cast(initializeFunction), scriptState->executionContext(), holder, 0, 0, isolate);
            if (block.HasCaught()) {
                WTF_LOG_ERROR("Private script error: Object constructor threw an exception.\n");
                if (!block.Message().IsEmpty())
                    WTF_LOG_ERROR("%s\n", toCoreString(block.Message()->Get()).utf8().data());
                RELEASE_ASSERT_NOT_REACHED();
            }
        }

        // Inject the prototype object of the private script into the prototype chain of the holder object.
        // This is necessary to let the holder object use properties defined on the prototype object
        // of the private script. (e.g., if the prototype object has |foo|, the holder object should be able
        // to use it with |this.foo|.)
        if (classObject->GetPrototype() != holderObject->GetPrototype())
            classObject->SetPrototype(holderObject->GetPrototype());
        holderObject->SetPrototype(classObject);

        isInitialized = v8Boolean(true, isolate);
        V8HiddenValue::setHiddenValue(isolate, holderObject, V8HiddenValue::privateScriptObjectIsInitialized(isolate), isInitialized);
    }
}

v8::Handle<v8::Value> PrivateScriptRunner::installClassIfNeeded(LocalFrame* frame, String className)
{
    if (!frame)
        return v8::Handle<v8::Value>();
    v8::HandleScope handleScope(toIsolate(frame));
    v8::Handle<v8::Context> context = toV8Context(frame, DOMWrapperWorld::privateScriptIsolatedWorld());
    if (context.IsEmpty())
        return v8::Handle<v8::Value>();
    ScriptState* scriptState = ScriptState::from(context);
    if (!scriptState->executionContext())
        return v8::Handle<v8::Value>();

    ScriptState::Scope scope(scriptState);
    return classObjectOfPrivateScript(scriptState, className);
}

v8::Handle<v8::Value> PrivateScriptRunner::runDOMAttributeGetter(ScriptState* scriptState, String className, String attributeName, v8::Handle<v8::Value> holder)
{
    v8::Handle<v8::Object> classObject = classObjectOfPrivateScript(scriptState, className);
    v8::Handle<v8::Value> descriptor = classObject->GetOwnPropertyDescriptor(v8String(scriptState->isolate(), attributeName));
    if (descriptor.IsEmpty() || !descriptor->IsObject()) {
        WTF_LOG_ERROR("Private script error: Target DOM attribute getter was not found. (Class name = %s, Attribute name = %s)\n", className.utf8().data(), attributeName.utf8().data());
        RELEASE_ASSERT_NOT_REACHED();
    }
    v8::Handle<v8::Value> getter = v8::Handle<v8::Object>::Cast(descriptor)->Get(v8String(scriptState->isolate(), "get"));
    if (getter.IsEmpty() || !getter->IsFunction()) {
        WTF_LOG_ERROR("Private script error: Target DOM attribute getter was not found. (Class name = %s, Attribute name = %s)\n", className.utf8().data(), attributeName.utf8().data());
        RELEASE_ASSERT_NOT_REACHED();
    }
    initializeHolderIfNeeded(scriptState, classObject, holder);
    return V8ScriptRunner::callFunction(v8::Handle<v8::Function>::Cast(getter), scriptState->executionContext(), holder, 0, 0, scriptState->isolate());
}

void PrivateScriptRunner::runDOMAttributeSetter(ScriptState* scriptState, String className, String attributeName, v8::Handle<v8::Value> holder, v8::Handle<v8::Value> v8Value)
{
    v8::Handle<v8::Object> classObject = classObjectOfPrivateScript(scriptState, className);
    v8::Handle<v8::Value> descriptor = classObject->GetOwnPropertyDescriptor(v8String(scriptState->isolate(), attributeName));
    if (descriptor.IsEmpty() || !descriptor->IsObject()) {
        WTF_LOG_ERROR("Private script error: Target DOM attribute setter was not found. (Class name = %s, Attribute name = %s)\n", className.utf8().data(), attributeName.utf8().data());
        RELEASE_ASSERT_NOT_REACHED();
    }
    v8::Handle<v8::Value> setter = v8::Handle<v8::Object>::Cast(descriptor)->Get(v8String(scriptState->isolate(), "set"));
    if (setter.IsEmpty() || !setter->IsFunction()) {
        WTF_LOG_ERROR("Private script error: Target DOM attribute setter was not found. (Class name = %s, Attribute name = %s)\n", className.utf8().data(), attributeName.utf8().data());
        RELEASE_ASSERT_NOT_REACHED();
    }
    initializeHolderIfNeeded(scriptState, classObject, holder);
    v8::Handle<v8::Value> argv[] = { v8Value };
    V8ScriptRunner::callFunction(v8::Handle<v8::Function>::Cast(setter), scriptState->executionContext(), holder, WTF_ARRAY_LENGTH(argv), argv, scriptState->isolate());
}

v8::Handle<v8::Value> PrivateScriptRunner::runDOMMethod(ScriptState* scriptState, String className, String methodName, v8::Handle<v8::Value> holder, int argc, v8::Handle<v8::Value> argv[])
{
    v8::Handle<v8::Object> classObject = classObjectOfPrivateScript(scriptState, className);
    v8::Handle<v8::Value> method = classObject->Get(v8String(scriptState->isolate(), methodName));
    if (method.IsEmpty() || !method->IsFunction()) {
        WTF_LOG_ERROR("Private script error: Target DOM method was not found. (Class name = %s, Method name = %s)\n", className.utf8().data(), methodName.utf8().data());
        RELEASE_ASSERT_NOT_REACHED();
    }
    initializeHolderIfNeeded(scriptState, classObject, holder);
    return V8ScriptRunner::callFunction(v8::Handle<v8::Function>::Cast(method), scriptState->executionContext(), holder, argc, argv, scriptState->isolate());
}

bool PrivateScriptRunner::throwDOMExceptionInPrivateScriptIfNeeded(v8::Isolate* isolate, ExceptionState& exceptionState, v8::Handle<v8::Value> exception)
{
    if (exception.IsEmpty() || !exception->IsObject())
        return false;

    v8::Handle<v8::Object> exceptionObject = v8::Handle<v8::Object>::Cast(exception);
    v8::Handle<v8::Value> name = exceptionObject->Get(v8String(isolate, "name"));
    if (name.IsEmpty() || !name->IsString())
        return false;
    String exceptionName = toCoreString(v8::Handle<v8::String>::Cast(name));
    if (exceptionName == "DOMExceptionInPrivateScript") {
        v8::Handle<v8::Value> message = exceptionObject->Get(v8String(isolate, "message"));
        RELEASE_ASSERT(!message.IsEmpty() && message->IsString());
        v8::Handle<v8::Value> code = exceptionObject->Get(v8String(isolate, "code"));
        RELEASE_ASSERT(!code.IsEmpty() && code->IsInt32());
        exceptionState.throwDOMException(toInt32(code), toCoreString(v8::Handle<v8::String>::Cast(message)));
        exceptionState.throwIfNeeded();
        return true;
    }
    if (exceptionName == "Error") {
        v8::Handle<v8::Value> message = exceptionObject->Get(v8String(isolate, "message"));
        RELEASE_ASSERT(!message.IsEmpty() && message->IsString());
        exceptionState.throwDOMException(V8GeneralError, toCoreString(v8::Handle<v8::String>::Cast(message)));
        exceptionState.throwIfNeeded();
        return true;
    }
    if (exceptionName == "TypeError") {
        v8::Handle<v8::Value> message = exceptionObject->Get(v8String(isolate, "message"));
        RELEASE_ASSERT(!message.IsEmpty() && message->IsString());
        exceptionState.throwDOMException(V8TypeError, toCoreString(v8::Handle<v8::String>::Cast(message)));
        exceptionState.throwIfNeeded();
        return true;
    }
    if (exceptionName == "RangeError") {
        v8::Handle<v8::Value> message = exceptionObject->Get(v8String(isolate, "message"));
        RELEASE_ASSERT(!message.IsEmpty() && message->IsString());
        exceptionState.throwDOMException(V8RangeError, toCoreString(v8::Handle<v8::String>::Cast(message)));
        exceptionState.throwIfNeeded();
        return true;
    }
    if (exceptionName == "SyntaxError") {
        v8::Handle<v8::Value> message = exceptionObject->Get(v8String(isolate, "message"));
        RELEASE_ASSERT(!message.IsEmpty() && message->IsString());
        exceptionState.throwDOMException(V8SyntaxError, toCoreString(v8::Handle<v8::String>::Cast(message)));
        exceptionState.throwIfNeeded();
        return true;
    }
    if (exceptionName == "ReferenceError") {
        v8::Handle<v8::Value> message = exceptionObject->Get(v8String(isolate, "message"));
        RELEASE_ASSERT(!message.IsEmpty() && message->IsString());
        exceptionState.throwDOMException(V8ReferenceError, toCoreString(v8::Handle<v8::String>::Cast(message)));
        exceptionState.throwIfNeeded();
        return true;
    }
    return false;
}

} // namespace blink
<commit_msg>Add WTF_LOG_ALWAYS and use it in PrivateScriptRunner<commit_after>// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "config.h"
#include "bindings/core/v8/PrivateScriptRunner.h"

#include "bindings/core/v8/DOMWrapperWorld.h"
#include "bindings/core/v8/ExceptionState.h"
#include "bindings/core/v8/V8Binding.h"
#include "bindings/core/v8/V8PerContextData.h"
#include "bindings/core/v8/V8ScriptRunner.h"
#include "core/PrivateScriptSources.h"
#ifndef NDEBUG
#include "core/PrivateScriptSourcesForTesting.h"
#endif
#include "core/dom/ExceptionCode.h"

namespace blink {

#define LOG_ERROR_ALWAYS(...) WTFReportError(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, __VA_ARGS__)

static v8::Handle<v8::Value> compilePrivateScript(v8::Isolate* isolate, String className)
{
    size_t index;
#ifndef NDEBUG
    for (index = 0; index < WTF_ARRAY_LENGTH(kPrivateScriptSourcesForTesting); index++) {
        if (className == kPrivateScriptSourcesForTesting[index].name)
            break;
    }
    if (index != WTF_ARRAY_LENGTH(kPrivateScriptSourcesForTesting)) {
        String source(reinterpret_cast<const char*>(kPrivateScriptSourcesForTesting[index].source), kPrivateScriptSourcesForTesting[index].size);
        return V8ScriptRunner::compileAndRunInternalScript(v8String(isolate, source), isolate);
    }
#endif

    // |kPrivateScriptSources| is defined in V8PrivateScriptSources.h, which is auto-generated
    // by make_private_script.py.
    for (index = 0; index < WTF_ARRAY_LENGTH(kPrivateScriptSources); index++) {
        if (className == kPrivateScriptSources[index].name)
            break;
    }
    if (index == WTF_ARRAY_LENGTH(kPrivateScriptSources)) {
        LOG_ERROR_ALWAYS("Private script error: Target source code was not found. (Class name = %s)\n", className.utf8().data());
        RELEASE_ASSERT_NOT_REACHED();
    }

    v8::TryCatch block;
    String source(reinterpret_cast<const char*>(kPrivateScriptSources[index].source), kPrivateScriptSources[index].size);
    v8::Handle<v8::Value> result = V8ScriptRunner::compileAndRunInternalScript(v8String(isolate, source), isolate);
    if (block.HasCaught()) {
        LOG_ERROR_ALWAYS("Private script error: Compile failed. (Class name = %s)\n", className.utf8().data());
        if (!block.Message().IsEmpty())
            LOG_ERROR_ALWAYS("%s\n", toCoreString(block.Message()->Get()).utf8().data());
        RELEASE_ASSERT_NOT_REACHED();
    }
    return result;
}

static v8::Handle<v8::Object> classObjectOfPrivateScript(ScriptState* scriptState, String className)
{
    ASSERT(scriptState->perContextData());
    ASSERT(scriptState->executionContext());
    v8::Isolate* isolate = scriptState->isolate();
    v8::Handle<v8::Value> compiledClass = scriptState->perContextData()->compiledPrivateScript(className);
    if (compiledClass.IsEmpty()) {
        v8::Handle<v8::Value> installedClasses = scriptState->perContextData()->compiledPrivateScript("PrivateScriptRunner");
        if (installedClasses.IsEmpty()) {
            installedClasses = compilePrivateScript(isolate, "PrivateScriptRunner");
            scriptState->perContextData()->setCompiledPrivateScript("PrivateScriptRunner", installedClasses);
        }
        RELEASE_ASSERT(!installedClasses.IsEmpty());
        RELEASE_ASSERT(installedClasses->IsObject());

        compilePrivateScript(isolate, className);
        compiledClass = v8::Handle<v8::Object>::Cast(installedClasses)->Get(v8String(isolate, className));
        RELEASE_ASSERT(!compiledClass.IsEmpty());
        RELEASE_ASSERT(compiledClass->IsObject());
        scriptState->perContextData()->setCompiledPrivateScript(className, compiledClass);
    }
    return v8::Handle<v8::Object>::Cast(compiledClass);
}

static void initializeHolderIfNeeded(ScriptState* scriptState, v8::Handle<v8::Object> classObject, v8::Handle<v8::Value> holder)
{
    RELEASE_ASSERT(!holder.IsEmpty());
    RELEASE_ASSERT(holder->IsObject());
    v8::Handle<v8::Object> holderObject = v8::Handle<v8::Object>::Cast(holder);
    v8::Isolate* isolate = scriptState->isolate();
    v8::Handle<v8::Value> isInitialized = V8HiddenValue::getHiddenValue(isolate, holderObject, V8HiddenValue::privateScriptObjectIsInitialized(isolate));
    if (isInitialized.IsEmpty()) {
        v8::TryCatch block;
        v8::Handle<v8::Value> initializeFunction = classObject->Get(v8String(isolate, "initialize"));
        if (!initializeFunction.IsEmpty() && initializeFunction->IsFunction()) {
            v8::TryCatch block;
            V8ScriptRunner::callFunction(v8::Handle<v8::Function>::Cast(initializeFunction), scriptState->executionContext(), holder, 0, 0, isolate);
            if (block.HasCaught()) {
                LOG_ERROR_ALWAYS("Private script error: Object constructor threw an exception.\n");
                if (!block.Message().IsEmpty())
                    LOG_ERROR_ALWAYS("%s\n", toCoreString(block.Message()->Get()).utf8().data());
                RELEASE_ASSERT_NOT_REACHED();
            }
        }

        // Inject the prototype object of the private script into the prototype chain of the holder object.
        // This is necessary to let the holder object use properties defined on the prototype object
        // of the private script. (e.g., if the prototype object has |foo|, the holder object should be able
        // to use it with |this.foo|.)
        if (classObject->GetPrototype() != holderObject->GetPrototype())
            classObject->SetPrototype(holderObject->GetPrototype());
        holderObject->SetPrototype(classObject);

        isInitialized = v8Boolean(true, isolate);
        V8HiddenValue::setHiddenValue(isolate, holderObject, V8HiddenValue::privateScriptObjectIsInitialized(isolate), isInitialized);
    }
}

v8::Handle<v8::Value> PrivateScriptRunner::installClassIfNeeded(LocalFrame* frame, String className)
{
    if (!frame)
        return v8::Handle<v8::Value>();
    v8::HandleScope handleScope(toIsolate(frame));
    v8::Handle<v8::Context> context = toV8Context(frame, DOMWrapperWorld::privateScriptIsolatedWorld());
    if (context.IsEmpty())
        return v8::Handle<v8::Value>();
    ScriptState* scriptState = ScriptState::from(context);
    if (!scriptState->executionContext())
        return v8::Handle<v8::Value>();

    ScriptState::Scope scope(scriptState);
    return classObjectOfPrivateScript(scriptState, className);
}

v8::Handle<v8::Value> PrivateScriptRunner::runDOMAttributeGetter(ScriptState* scriptState, String className, String attributeName, v8::Handle<v8::Value> holder)
{
    v8::Handle<v8::Object> classObject = classObjectOfPrivateScript(scriptState, className);
    v8::Handle<v8::Value> descriptor = classObject->GetOwnPropertyDescriptor(v8String(scriptState->isolate(), attributeName));
    if (descriptor.IsEmpty() || !descriptor->IsObject()) {
        LOG_ERROR_ALWAYS("Private script error: Target DOM attribute getter was not found. (Class name = %s, Attribute name = %s)\n", className.utf8().data(), attributeName.utf8().data());
        RELEASE_ASSERT_NOT_REACHED();
    }
    v8::Handle<v8::Value> getter = v8::Handle<v8::Object>::Cast(descriptor)->Get(v8String(scriptState->isolate(), "get"));
    if (getter.IsEmpty() || !getter->IsFunction()) {
        LOG_ERROR_ALWAYS("Private script error: Target DOM attribute getter was not found. (Class name = %s, Attribute name = %s)\n", className.utf8().data(), attributeName.utf8().data());
        RELEASE_ASSERT_NOT_REACHED();
    }
    initializeHolderIfNeeded(scriptState, classObject, holder);
    return V8ScriptRunner::callFunction(v8::Handle<v8::Function>::Cast(getter), scriptState->executionContext(), holder, 0, 0, scriptState->isolate());
}

void PrivateScriptRunner::runDOMAttributeSetter(ScriptState* scriptState, String className, String attributeName, v8::Handle<v8::Value> holder, v8::Handle<v8::Value> v8Value)
{
    v8::Handle<v8::Object> classObject = classObjectOfPrivateScript(scriptState, className);
    v8::Handle<v8::Value> descriptor = classObject->GetOwnPropertyDescriptor(v8String(scriptState->isolate(), attributeName));
    if (descriptor.IsEmpty() || !descriptor->IsObject()) {
        LOG_ERROR_ALWAYS("Private script error: Target DOM attribute setter was not found. (Class name = %s, Attribute name = %s)\n", className.utf8().data(), attributeName.utf8().data());
        RELEASE_ASSERT_NOT_REACHED();
    }
    v8::Handle<v8::Value> setter = v8::Handle<v8::Object>::Cast(descriptor)->Get(v8String(scriptState->isolate(), "set"));
    if (setter.IsEmpty() || !setter->IsFunction()) {
        LOG_ERROR_ALWAYS("Private script error: Target DOM attribute setter was not found. (Class name = %s, Attribute name = %s)\n", className.utf8().data(), attributeName.utf8().data());
        RELEASE_ASSERT_NOT_REACHED();
    }
    initializeHolderIfNeeded(scriptState, classObject, holder);
    v8::Handle<v8::Value> argv[] = { v8Value };
    V8ScriptRunner::callFunction(v8::Handle<v8::Function>::Cast(setter), scriptState->executionContext(), holder, WTF_ARRAY_LENGTH(argv), argv, scriptState->isolate());
}

v8::Handle<v8::Value> PrivateScriptRunner::runDOMMethod(ScriptState* scriptState, String className, String methodName, v8::Handle<v8::Value> holder, int argc, v8::Handle<v8::Value> argv[])
{
    v8::Handle<v8::Object> classObject = classObjectOfPrivateScript(scriptState, className);
    v8::Handle<v8::Value> method = classObject->Get(v8String(scriptState->isolate(), methodName));
    if (method.IsEmpty() || !method->IsFunction()) {
        LOG_ERROR_ALWAYS("Private script error: Target DOM method was not found. (Class name = %s, Method name = %s)\n", className.utf8().data(), methodName.utf8().data());
        RELEASE_ASSERT_NOT_REACHED();
    }
    initializeHolderIfNeeded(scriptState, classObject, holder);
    return V8ScriptRunner::callFunction(v8::Handle<v8::Function>::Cast(method), scriptState->executionContext(), holder, argc, argv, scriptState->isolate());
}

bool PrivateScriptRunner::throwDOMExceptionInPrivateScriptIfNeeded(v8::Isolate* isolate, ExceptionState& exceptionState, v8::Handle<v8::Value> exception)
{
    if (exception.IsEmpty() || !exception->IsObject())
        return false;

    v8::Handle<v8::Object> exceptionObject = v8::Handle<v8::Object>::Cast(exception);
    v8::Handle<v8::Value> name = exceptionObject->Get(v8String(isolate, "name"));
    if (name.IsEmpty() || !name->IsString())
        return false;
    String exceptionName = toCoreString(v8::Handle<v8::String>::Cast(name));
    if (exceptionName == "DOMExceptionInPrivateScript") {
        v8::Handle<v8::Value> message = exceptionObject->Get(v8String(isolate, "message"));
        RELEASE_ASSERT(!message.IsEmpty() && message->IsString());
        v8::Handle<v8::Value> code = exceptionObject->Get(v8String(isolate, "code"));
        RELEASE_ASSERT(!code.IsEmpty() && code->IsInt32());
        exceptionState.throwDOMException(toInt32(code), toCoreString(v8::Handle<v8::String>::Cast(message)));
        exceptionState.throwIfNeeded();
        return true;
    }
    if (exceptionName == "Error") {
        v8::Handle<v8::Value> message = exceptionObject->Get(v8String(isolate, "message"));
        RELEASE_ASSERT(!message.IsEmpty() && message->IsString());
        exceptionState.throwDOMException(V8GeneralError, toCoreString(v8::Handle<v8::String>::Cast(message)));
        exceptionState.throwIfNeeded();
        return true;
    }
    if (exceptionName == "TypeError") {
        v8::Handle<v8::Value> message = exceptionObject->Get(v8String(isolate, "message"));
        RELEASE_ASSERT(!message.IsEmpty() && message->IsString());
        exceptionState.throwDOMException(V8TypeError, toCoreString(v8::Handle<v8::String>::Cast(message)));
        exceptionState.throwIfNeeded();
        return true;
    }
    if (exceptionName == "RangeError") {
        v8::Handle<v8::Value> message = exceptionObject->Get(v8String(isolate, "message"));
        RELEASE_ASSERT(!message.IsEmpty() && message->IsString());
        exceptionState.throwDOMException(V8RangeError, toCoreString(v8::Handle<v8::String>::Cast(message)));
        exceptionState.throwIfNeeded();
        return true;
    }
    if (exceptionName == "SyntaxError") {
        v8::Handle<v8::Value> message = exceptionObject->Get(v8String(isolate, "message"));
        RELEASE_ASSERT(!message.IsEmpty() && message->IsString());
        exceptionState.throwDOMException(V8SyntaxError, toCoreString(v8::Handle<v8::String>::Cast(message)));
        exceptionState.throwIfNeeded();
        return true;
    }
    if (exceptionName == "ReferenceError") {
        v8::Handle<v8::Value> message = exceptionObject->Get(v8String(isolate, "message"));
        RELEASE_ASSERT(!message.IsEmpty() && message->IsString());
        exceptionState.throwDOMException(V8ReferenceError, toCoreString(v8::Handle<v8::String>::Cast(message)));
        exceptionState.throwIfNeeded();
        return true;
    }
    return false;
}

} // namespace blink
<|endoftext|>


<commit_before>/*
 * main.cpp -- This file is part of primesieve
 *
 * Copyright (C) 2011 Kim Walisch, <kim.walisch@gmail.com>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.

 * This program 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>
 */

/**
 * @file main.cpp
 * @brief Command line version of PrimeSieve, compiles on many
 * platforms, single-threaded.
 *
 * PrimeSieve is a highly optimized implementation of the sieve of
 * Eratosthenes that finds prime numbers and prime k-tuplets (twin
 * primes, prime triplets, ...) up to 2^64 maximum.
 */

#include "../src/PrimeSieve.h"
#include "../src/pmath.h"
#include "../thirdparty/eval11/ArithmeticExpression.h"
#include "test.h"

#include <stdint.h>
#include <exception>
#include <iostream>
#include <cstdlib>
#include <cctype>
#include <ctime>
#include <string>
#include <cstring>
#include <iomanip>

// Unfortunately there is no easy way to get the CPU L1 and L2 cache
// size, these values are close for most x86-64 CPUs in 2011
#define L1_CACHE_SIZE 64
#define L2_CACHE_SIZE 512
#define L2_THRESHOLD ipow(10, 12)

// PrimeSieve arguments
uint64_t start = 0;      /* lower bound for sieving */
uint64_t stop = 0;       /* upper bound for sieving */
uint32_t flags = 0;      /* settings */
uint32_t sieveSize = 0;  /* sieve size in KiloBytes */

bool quietMode = false;
bool showArithmeticExpressionResults = false;

std::string primes[7] = { "Prime numbers", "Twin primes", "Prime triplets",
    "Prime quadruplets", "Prime quintuplets", "Prime sextuplets",
    "Prime septuplets" };

void version() {
  std::cout << "primesieve 1.1, <http://primesieve.googlecode.com>"
      << std::endl << "Copyright (C) 2011 Kim Walisch" << std::endl
      << "License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>."
      << std::endl
      << "This is free software: you are free to change and redistribute it."
      << std::endl << "There is NO WARRANTY, to the extent permitted by law."
      << std::endl;
}

void help() {
  std::cout << "Usage: primesieve START STOP [OPTION]..." << std::endl
      << "Use the sieve of Eratosthenes to find the prime numbers and prime" << std::endl
      << "k-tuplets between START and STOP < 2^64" << std::endl
      << std::endl
      << "Examples:" << std::endl
      << "  primesieve 1 10000000 -p1" << std::endl
      << "  primesieve 1 1e11 -s 32" << std::endl
      << "  primesieve 1e18 1e18+2**32 -c1 -c2" << std::endl
      << std::endl
      << "Options:" << std::endl
      << "  -s <size>  Set the sieve size (in KiloBytes)," << std::endl
      << "             size >= 1 && size <= 8192" << std::endl
      << "             Set size to your CPU's L1 or L2 cache size for best performance" << std::endl
      << "  -q         Quiet mode, less output" << std::endl
      << "  -test      Run various sieving tests" << std::endl
      << "  -v         Print version and license information and exit"
      << std::endl;
  for (char c = '1'; c <= '7'; c++)
    std::cout << "  -c" << c << "        Count " << primes[c - '1'] << std::endl;
  for (char c = '1'; c <= '7'; c++)
    std::cout << "  -p" << c << "        Print " << primes[c - '1'] << std::endl;
  exit(EXIT_SUCCESS);
}

/**
 * Process the command line options.
 * -c[n], count prime numbers and/or prime k-tuplets
 * -p[n], print prime numbers and/or prime k-tuplets
 * -s <size>, set the sieve size in KiloBytes
 * -v, print version information
 */
void processOptions(int argc, char* argv[]) {
  if (argc == 1 || argc > 2 * 7 + 3)
    help();
  int i = 1;
  // Arithmetic expression parser
  ArithmeticExpression expr;
  if (argc > 2) {
    if (!expr.evaluate(argv[i++])) {
      std::cerr << "START is not a valid expression: "
                << expr.getErrorMessage()
                << std::endl
                << "Try `primesieve -help' for more information."
                << std::endl;
      exit(EXIT_FAILURE);
    }
    start = expr.getResult();
    if (!expr.isPlainInteger())
      showArithmeticExpressionResults = true;
    if (!expr.evaluate(argv[i++])) {
      std::cerr << "STOP is not a valid expression: "
                << expr.getErrorMessage()
                << std::endl
                << "Try `primesieve -help' for more information."
                << std::endl;
      exit(EXIT_FAILURE);
    }
    stop = expr.getResult();
    if (!expr.isPlainInteger())
      showArithmeticExpressionResults = true;
  }
  for (; i < argc; i++) {
    if (*argv[i] == '-' || *argv[i] == '/')
      argv[i]++;
    int x = -1;
    switch (std::tolower(*argv[i])) {
    case 'c':
      x = argv[i][1] - '0';
      if (x < 1 || x > 7)
        help();
      flags |= COUNT_PRIMES << (x - 1);
      break;
    case 'p':
      x = argv[i][1] - '0';
      if (x < 1 || x > 7)
        help();
      flags |= PRINT_PRIMES << (x - 1);
      quietMode = true;
      break;
    case 'q':
      quietMode = true;
      break;
    case 's':
      if (argv[++i] == NULL)
        help();
      if (!expr.evaluate(argv[i]))
        help();
      sieveSize = static_cast<uint32_t> (expr.getResult());
      if (sieveSize < 1 || sieveSize > 8192)
        help();
      // PrimeSieve requires a power of 2 sieve size
      sieveSize = nextHighestPowerOf2(sieveSize);
      break;
    case 't':
      test();
      exit(EXIT_SUCCESS);
    case 'v':
      version();
      exit(EXIT_SUCCESS);
    default:
      help();
      exit(EXIT_SUCCESS);
    }
  }
}

void setDefaultSettings() {
  // count prime numbers if none else selected
  if ((flags & COUNT_FLAGS) == 0)
    flags |= COUNT_PRIMES;
  if (sieveSize == 0) {
    // L1 cache size gives best performance for small primes
    // L2 cache size gives best performance for big primes
    sieveSize = (stop < L2_THRESHOLD)
        ? L1_CACHE_SIZE : L2_CACHE_SIZE;
  }
}

/**
 * @return maximum output string length.
 */
int getMaxLength() {
  int maxLength = static_cast<int> (std::strlen("Time elapsed"));
  // find bigger prime string
  for (int i = 0; i < 7; i++) {
    if (flags & (COUNT_PRIMES << i)) {
      int length = static_cast<int> (primes[i].length());
      if (length > maxLength)
        maxLength = length;
    }
  }
  return maxLength;
}

/**
 * Process the command line options, initialize PrimeSieve and then
 * start sieving.
 */
int main(int argc, char* argv[]) {
  processOptions(argc, argv);
  setDefaultSettings();
  // set left output alignment
  std::cout.setf(std::ios::left);
  // get maximum output string length
  int maxLength = getMaxLength();
  // display arithmetic expression results
  if (!quietMode &&
       showArithmeticExpressionResults) {
    std::cout << std::setw(maxLength)
              << "START"
              << " = "
              << start
              << std::endl
              << std::setw(maxLength)
              << "STOP"
              << " = "
              << stop
              << std::endl;
  }
  if (start > stop) {
    std::cerr << "STOP must be >= START" << std::endl;
    exit(EXIT_FAILURE);
  }
  if (stop >= UINT64_MAX - UINT32_MAX * UINT64_C(10)) {
    std::cerr << "STOP must be < (2^64-1) - (2^32-1) * 10." << std::endl;
    exit(EXIT_FAILURE);
  }
  if ((flags & PRINT_FLAGS) == 0) {
    // print the status whilst sieving
    flags |= PRINT_STATUS;
    if (!quietMode)
      std::cout << std::setw(maxLength)
                << "Sieve size"
                << " = "
                << sieveSize
                << " KiloBytes"
                << std::endl;
  }
  std::clock_t begin = std::clock();
  try {
    // initialize primeSieve
    PrimeSieve primeSieve;
    primeSieve.setStartNumber(start);
    primeSieve.setStopNumber(stop);
    primeSieve.setSieveSize(sieveSize);
    primeSieve.setFlags(flags);
    // start sieving primes
    primeSieve.sieve();
    std::clock_t end = std::clock();
    // new line if printing is enabled
    if ((flags & PRINT_FLAGS) != 0)
      std::cout << std::endl;
    // print the prime count results
    for (int i = 0; i < 7; i++) {
      if (flags & (COUNT_PRIMES << i))
        std::cout << std::setw(maxLength)
                  << primes[i]
                  << " : "
                  << primeSieve.getCounts(i)
                  << std::endl;
    }
    std::cout << std::setw(maxLength)
              << "Time elapsed"
              << " : "
              << ((end - begin) / static_cast<double> (CLOCKS_PER_SEC))
              << " sec"
              << std::endl;
  } catch (std::exception& ex) {
    std::cerr << "Exception " << ex.what() << std::endl;
    exit(EXIT_FAILURE);
  }
  return 0;
}
<commit_msg>do not show prime counts when printing<commit_after>/*
 * main.cpp -- This file is part of primesieve
 *
 * Copyright (C) 2011 Kim Walisch, <kim.walisch@gmail.com>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.

 * This program 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>
 */

/**
 * @file main.cpp
 * @brief Command line version of PrimeSieve, compiles on many
 * platforms, single-threaded.
 *
 * PrimeSieve is a highly optimized implementation of the sieve of
 * Eratosthenes that finds prime numbers and prime k-tuplets (twin
 * primes, prime triplets, ...) up to 2^64 maximum.
 */

#include "../src/PrimeSieve.h"
#include "../src/pmath.h"
#include "../thirdparty/eval11/ArithmeticExpression.h"
#include "test.h"

#include <stdint.h>
#include <exception>
#include <iostream>
#include <cstdlib>
#include <cctype>
#include <ctime>
#include <string>
#include <cstring>
#include <iomanip>

// Unfortunately there is no easy way to get the CPU L1 and L2 cache
// size, these values are close for most x86-64 CPUs in 2011
#define L1_CACHE_SIZE 64
#define L2_CACHE_SIZE 512
#define L2_THRESHOLD ipow(10, 12)

// PrimeSieve arguments
uint64_t start = 0;      /* lower bound for sieving */
uint64_t stop = 0;       /* upper bound for sieving */
uint32_t flags = 0;      /* settings */
uint32_t sieveSize = 0;  /* sieve size in KiloBytes */

bool quietMode = false;
bool showArithmeticExpressionResults = false;

std::string primes[7] = { "Prime numbers", "Twin primes", "Prime triplets",
    "Prime quadruplets", "Prime quintuplets", "Prime sextuplets",
    "Prime septuplets" };

void version() {
  std::cout << "primesieve 1.1, <http://primesieve.googlecode.com>"
      << std::endl << "Copyright (C) 2011 Kim Walisch" << std::endl
      << "License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>."
      << std::endl
      << "This is free software: you are free to change and redistribute it."
      << std::endl << "There is NO WARRANTY, to the extent permitted by law."
      << std::endl;
}

void help() {
  std::cout << "Usage: primesieve START STOP [OPTION]..." << std::endl
      << "Use the sieve of Eratosthenes to find the prime numbers and prime" << std::endl
      << "k-tuplets between START and STOP < 2^64" << std::endl
      << std::endl
      << "Examples:" << std::endl
      << "  primesieve 1 10000000 -p1" << std::endl
      << "  primesieve 1 1e11 -s 32" << std::endl
      << "  primesieve 1e18 1e18+2**32 -c1 -c2" << std::endl
      << std::endl
      << "Options:" << std::endl
      << "  -s <size>  Set the sieve size (in KiloBytes)," << std::endl
      << "             size >= 1 && size <= 8192" << std::endl
      << "             Set size to your CPU's L1 or L2 cache size for best performance" << std::endl
      << "  -q         Quiet mode, less output" << std::endl
      << "  -test      Run various sieving tests" << std::endl
      << "  -v         Print version and license information and exit"
      << std::endl;
  for (char c = '1'; c <= '7'; c++)
    std::cout << "  -c" << c << "        Count " << primes[c - '1'] << std::endl;
  for (char c = '1'; c <= '7'; c++)
    std::cout << "  -p" << c << "        Print " << primes[c - '1'] << std::endl;
  exit(EXIT_SUCCESS);
}

/**
 * Process the command line options.
 * -c[n], count prime numbers and/or prime k-tuplets
 * -p[n], print prime numbers and/or prime k-tuplets
 * -s <size>, set the sieve size in KiloBytes
 * -v, print version information
 */
void processOptions(int argc, char* argv[]) {
  if (argc == 1 || argc > 2 * 7 + 3)
    help();
  int i = 1;
  // Arithmetic expression parser
  ArithmeticExpression expr;
  if (argc > 2) {
    if (!expr.evaluate(argv[i++])) {
      std::cerr << "START is not a valid expression: "
                << expr.getErrorMessage()
                << std::endl
                << "Try `primesieve -help' for more information."
                << std::endl;
      exit(EXIT_FAILURE);
    }
    start = expr.getResult();
    if (!expr.isPlainInteger())
      showArithmeticExpressionResults = true;
    if (!expr.evaluate(argv[i++])) {
      std::cerr << "STOP is not a valid expression: "
                << expr.getErrorMessage()
                << std::endl
                << "Try `primesieve -help' for more information."
                << std::endl;
      exit(EXIT_FAILURE);
    }
    stop = expr.getResult();
    if (!expr.isPlainInteger())
      showArithmeticExpressionResults = true;
  }
  for (; i < argc; i++) {
    if (*argv[i] == '-' || *argv[i] == '/')
      argv[i]++;
    int x = -1;
    switch (std::tolower(*argv[i])) {
    case 'c':
      x = argv[i][1] - '0';
      if (x < 1 || x > 7)
        help();
      flags |= COUNT_PRIMES << (x - 1);
      break;
    case 'p':
      x = argv[i][1] - '0';
      if (x < 1 || x > 7)
        help();
      flags |= PRINT_PRIMES << (x - 1);
      quietMode = true;
      break;
    case 'q':
      quietMode = true;
      break;
    case 's':
      if (argv[++i] == NULL)
        help();
      if (!expr.evaluate(argv[i]))
        help();
      sieveSize = static_cast<uint32_t> (expr.getResult());
      if (sieveSize < 1 || sieveSize > 8192)
        help();
      // PrimeSieve requires a power of 2 sieve size
      sieveSize = nextHighestPowerOf2(sieveSize);
      break;
    case 't':
      test();
      exit(EXIT_SUCCESS);
    case 'v':
      version();
      exit(EXIT_SUCCESS);
    default:
      help();
      exit(EXIT_SUCCESS);
    }
  }
}

void setDefaultSettings() {
  // count prime numbers if none else selected
  if ((flags & COUNT_FLAGS) == 0 &&
      (flags & PRINT_FLAGS) == 0)
    flags |= COUNT_PRIMES;
  if (sieveSize == 0) {
    // L1 cache size gives best performance for small primes
    // L2 cache size gives best performance for big primes
    sieveSize = (stop < L2_THRESHOLD)
        ? L1_CACHE_SIZE : L2_CACHE_SIZE;
  }
}

/**
 * @return maximum output string length.
 */
int getMaxLength() {
  int maxLength = static_cast<int> (std::strlen("Time elapsed"));
  // find bigger prime string
  for (int i = 0; i < 7; i++) {
    if (flags & (COUNT_PRIMES << i)) {
      int length = static_cast<int> (primes[i].length());
      if (length > maxLength)
        maxLength = length;
    }
  }
  return maxLength;
}

/**
 * Process the command line options, initialize PrimeSieve and then
 * start sieving.
 */
int main(int argc, char* argv[]) {
  processOptions(argc, argv);
  setDefaultSettings();
  // set left output alignment
  std::cout.setf(std::ios::left);
  // get maximum output string length
  int maxLength = getMaxLength();
  // display arithmetic expression results
  if (!quietMode &&
       showArithmeticExpressionResults) {
    std::cout << std::setw(maxLength)
              << "START"
              << " = "
              << start
              << std::endl
              << std::setw(maxLength)
              << "STOP"
              << " = "
              << stop
              << std::endl;
  }
  if (start > stop) {
    std::cerr << "STOP must be >= START" << std::endl;
    exit(EXIT_FAILURE);
  }
  if (stop >= UINT64_MAX - UINT32_MAX * UINT64_C(10)) {
    std::cerr << "STOP must be < (2^64-1) - (2^32-1) * 10." << std::endl;
    exit(EXIT_FAILURE);
  }
  if ((flags & PRINT_FLAGS) == 0) {
    // print the status whilst sieving
    flags |= PRINT_STATUS;
    if (!quietMode)
      std::cout << std::setw(maxLength)
                << "Sieve size"
                << " = "
                << sieveSize
                << " KiloBytes"
                << std::endl;
  }
  std::clock_t begin = std::clock();
  try {
    // initialize primeSieve
    PrimeSieve primeSieve;
    primeSieve.setStartNumber(start);
    primeSieve.setStopNumber(stop);
    primeSieve.setSieveSize(sieveSize);
    primeSieve.setFlags(flags);
    // start sieving primes
    primeSieve.sieve();
    std::clock_t end = std::clock();
    // new line if printing is enabled
    if ((flags & PRINT_FLAGS) != 0)
      std::cout << std::endl;
    // print the prime count results
    for (int i = 0; i < 7; i++) {
      if (flags & (COUNT_PRIMES << i))
        std::cout << std::setw(maxLength)
                  << primes[i]
                  << " : "
                  << primeSieve.getCounts(i)
                  << std::endl;
    }
    std::cout << std::setw(maxLength)
              << "Time elapsed"
              << " : "
              << ((end - begin) / static_cast<double> (CLOCKS_PER_SEC))
              << " sec"
              << std::endl;
  } catch (std::exception& ex) {
    std::cerr << "Exception " << ex.what() << std::endl;
    exit(EXIT_FAILURE);
  }
  return 0;
}
<|endoftext|>


<commit_before>//hxcpp include should be first
#ifndef HXCPP_H
#include <hxcpp.h>
#endif
#include "./linc_empty.h"

namespace linc {

    namespace empty {

        int example() {
            return 55;
        }

    } //empty namespace

} //linc<commit_msg>even more attempts to fix hxcpp pch errors<commit_after>//hxcpp include should be first
#include <hxcpp.h>
#include "./linc_empty.h"

namespace linc {

    namespace empty {

        int example() {
            return 55;
        }

    } //empty namespace

} //linc<|endoftext|>


<commit_before>
 /**
 * \file      main.cc
 * \brief     Program for giving an indication when a rfid card has been detected, a database connection has been made and a string has been encrypted
 * \author    Tim IJntema, Stefan de Beer, Arco Gelderblom, Rik Honcoop, Koen de Groot, Ricardo Bouwman
 * \copyright Copyright (c) 2017, The R2D2 Team
 * \license   See LICENSE
 */

#include "mysql.hh"
#include "mfrc522.hh"
#include "led-controller.hh"
#include "matrix-keypad.hh"
#include "config-file-parser.hh"

#include <wiringPi.h>
#include <wiringPiSPI.h>

#include <iostream>

struct MFAuthentData {
    uint8_t command_code;
    uint8_t blockAddress;
    uint8_t sectorKey[5];
    uint8_t serialNumber[4];
};

int main(int argc, char **argv) {
    try {
        std::string ip;
        std::string username;
        std::string password;
        //int encryptionKey;

        ConfigFileParser factory("database-config.txt");
        factory.loadDatabaseSettings(ip, username, password);

        MySql connection;

        connection.connectTo(ip, username, password);
        connection.selectDatabase("R2D2");

        std::cout << "Made connection to the database\n";
        wiringPiSetup();
        wiringPiSPISetup(0, 10000000);//max speed for mfrc522 is 10Mhz
        MFRC522 rfid;
        rfid.PCD_Init();

        //Keypad pinSetup
        const int keypadRow[] = {4, 1, 16, 15};
        const int keypadColumn[] = {2, 7, 9, 8};

        //Keypad objects
        MatrixKeypad keypad(keypadRow, keypadColumn, 4);
        char c;

        LedController led(0);

        while (true) {
            delay(1000);
            std::cout << "\n\nWaiting for rfid tag: \n";

            if(!rfid.PICC_IsNewCardPresent())
                continue;
            if(!rfid.PICC_ReadCardSerial())
                continue;

            MFRC522::MIFARE_Key key = {0xFF, 0xFF, 0xFF, 0xFF};

            std::cout << "Input PIN and finish with #\n";

            long value = atol(keypad.getString().c_str());

            if(!rfid.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, (byte)0x03, &key, &rfid.uid))
                continue;

            if (!rfid.MIFARE_SetValue((byte)0x03, value))
                continue;

            if (!rfid.MIFARE_GetValue((byte)0x03, &value))
                continue;

            std::cout << value << '\n';

            rfid.PCD_StopCrypto1();

            for(byte i = 0; i < rfid.uid.size; ++i){
                if(rfid.uid.uidByte[i] < 0x10){
                    printf(" 0");
                    printf("%X",rfid.uid.uidByte[i]);
                }
                else{
                    printf(" ");
                    printf("%X", rfid.uid.uidByte[i]);
                }
            }

            connection.executeQuery("SELECT * FROM RFID");

            std::cout << "Database information: "
                      << connection.getPreviousResponseColumn("CARD_ID")
                      << '\n';

            led.blinkLed(1000);
        }
    } catch (const std::string &error) {
        std::cerr << error << '\n';
        exit(EXIT_FAILURE);
    } catch (...) {
        std::cerr << "Something went wrong\n";
        exit(EXIT_FAILURE);
    }
    return 0;
}

<commit_msg>[RFID-03] Fixed pin numbering to match what's on the wiki<commit_after>
 /**
 * \file      main.cc
 * \brief     Program for giving an indication when a rfid card has been detected, a database connection has been made and a string has been encrypted
 * \author    Tim IJntema, Stefan de Beer, Arco Gelderblom, Rik Honcoop, Koen de Groot, Ricardo Bouwman
 * \copyright Copyright (c) 2017, The R2D2 Team
 * \license   See LICENSE
 */

#include "mysql.hh"
#include "mfrc522.hh"
#include "led-controller.hh"
#include "matrix-keypad.hh"
#include "config-file-parser.hh"

#include <wiringPi.h>
#include <wiringPiSPI.h>

#include <iostream>

struct MFAuthentData {
    uint8_t command_code;
    uint8_t blockAddress;
    uint8_t sectorKey[5];
    uint8_t serialNumber[4];
};

int main(int argc, char **argv) {
    try {
        std::string ip;
        std::string username;
        std::string password;
        //int encryptionKey;

        ConfigFileParser factory("database-config.txt");
        factory.loadDatabaseSettings(ip, username, password);

        MySql connection;

        connection.connectTo(ip, username, password);
        connection.selectDatabase("R2D2");

        std::cout << "Made connection to the database\n";
        wiringPiSetup();
        wiringPiSPISetup(0, 10000000);//max speed for mfrc522 is 10Mhz
        MFRC522 rfid;
        rfid.PCD_Init();

        //Keypad pinSetup
        const int keypadRow[] = {15, 16, 1, 4};
        const int keypadColumn[] = {8, 9, 7, 2};

        //Keypad objects
        MatrixKeypad keypad(keypadRow, keypadColumn, 4);
        char c;

        LedController led(0);

        while (true) {
            delay(1000);
            std::cout << "\n\nWaiting for rfid tag: \n";

            if(!rfid.PICC_IsNewCardPresent())
                continue;
            if(!rfid.PICC_ReadCardSerial())
                continue;

            MFRC522::MIFARE_Key key = {0xFF, 0xFF, 0xFF, 0xFF};

            std::cout << "Input PIN and finish with #\n";

            long value = atol(keypad.getString().c_str());

            if(!rfid.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, (byte)0x03, &key, &rfid.uid))
                continue;

            if (!rfid.MIFARE_SetValue((byte)0x03, value))
                continue;

            if (!rfid.MIFARE_GetValue((byte)0x03, &value))
                continue;

            std::cout << value << '\n';

            rfid.PCD_StopCrypto1();

            for(byte i = 0; i < rfid.uid.size; ++i){
                if(rfid.uid.uidByte[i] < 0x10){
                    printf(" 0");
                    printf("%X",rfid.uid.uidByte[i]);
                }
                else{
                    printf(" ");
                    printf("%X", rfid.uid.uidByte[i]);
                }
            }

            connection.executeQuery("SELECT * FROM RFID");

            std::cout << "Database information: "
                      << connection.getPreviousResponseColumn("CARD_ID")
                      << '\n';

            led.blinkLed(1000);
        }
    } catch (const std::string &error) {
        std::cerr << error << '\n';
        exit(EXIT_FAILURE);
    } catch (...) {
        std::cerr << "Something went wrong\n";
        exit(EXIT_FAILURE);
    }
    return 0;
}

<|endoftext|>


<commit_before>// Copyright (c) 2021 The PIVX developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or https://www.opensource.org/licenses/mit-license.php.

#include "tiertwo/init.h"

#include "budget/budgetdb.h"
#include "evo/evodb.h"
#include "flatdb.h"
#include "guiinterface.h"
#include "guiinterfaceutil.h"
#include "masternodeman.h"
#include "masternode-payments.h"
#include "masternodeconfig.h"
#include "llmq/quorums_init.h"
#include "tiertwo/masternode_meta_manager.h"
#include "validation.h"
#include "wallet/wallet.h"

#include <boost/thread.hpp>

std::string GetTierTwoHelpString(bool showDebug)
{
    std::string strUsage = HelpMessageGroup("Masternode options:");
    strUsage += HelpMessageOpt("-masternode=<n>", strprintf("Enable the client to act as a masternode (0-1, default: %u)", DEFAULT_MASTERNODE));
    strUsage += HelpMessageOpt("-mnconf=<file>", strprintf("Specify masternode configuration file (default: %s)", PIVX_MASTERNODE_CONF_FILENAME));
    strUsage += HelpMessageOpt("-mnconflock=<n>", strprintf("Lock masternodes from masternode configuration file (default: %u)", DEFAULT_MNCONFLOCK));
    strUsage += HelpMessageOpt("-masternodeprivkey=<n>", "Set the masternode private key");
    strUsage += HelpMessageOpt("-masternodeaddr=<n>", strprintf("Set external address:port to get to this masternode (example: %s)", "128.127.106.235:51472"));
    strUsage += HelpMessageOpt("-budgetvotemode=<mode>", "Change automatic finalized budget voting behavior. mode=auto: Vote for only exact finalized budget match to my generated budget. (string, default: auto)");
    strUsage += HelpMessageOpt("-mnoperatorprivatekey=<WIF>", "Set the masternode operator private key. Only valid with -masternode=1. When set, the masternode acts as a deterministic masternode.");
    if (showDebug) {
        strUsage += HelpMessageOpt("-pushversion", strprintf("Modifies the mnauth serialization if the version is lower than %d."
                                                             "testnet/regtest only; ", MNAUTH_NODE_VER_VERSION));
        strUsage += HelpMessageOpt("-disabledkg", "Disable the DKG sessions process threads for the entire lifecycle. testnet/regtest only.");
    }
    return strUsage;
}

void InitTierTwoPreChainLoad(bool fReindex)
{
    int64_t nEvoDbCache = 1024 * 1024 * 16; // TODO
    deterministicMNManager.reset();
    evoDb.reset();
    evoDb.reset(new CEvoDB(nEvoDbCache, false, fReindex));
    deterministicMNManager.reset(new CDeterministicMNManager(*evoDb));
}

void InitTierTwoPostCoinsCacheLoad()
{
    // Initialize LLMQ system
    llmq::InitLLMQSystem(*evoDb);
}

// Sets the last CACHED_BLOCK_HASHES hashes into masternode manager cache
static void LoadBlockHashesCache(CMasternodeMan& man)
{
    LOCK(cs_main);
    const CBlockIndex* pindex = chainActive.Tip();
    unsigned int inserted = 0;
    while (pindex && inserted < CACHED_BLOCK_HASHES) {
        man.CacheBlockHash(pindex);
        pindex = pindex->pprev;
        ++inserted;
    }
}

bool LoadTierTwo(int chain_active_height, bool fReindexChainState)
{
    // ################################# //
    // ## Legacy Masternodes Manager ### //
    // ################################# //
    uiInterface.InitMessage(_("Loading masternode cache..."));

    mnodeman.SetBestHeight(chain_active_height);
    LoadBlockHashesCache(mnodeman);
    CMasternodeDB mndb;
    CMasternodeDB::ReadResult readResult = mndb.Read(mnodeman);
    if (readResult == CMasternodeDB::FileError)
        LogPrintf("Missing masternode cache file - mncache.dat, will try to recreate\n");
    else if (readResult != CMasternodeDB::Ok) {
        LogPrintf("Error reading mncache.dat - cached data discarded\n");
    }

    // ##################### //
    // ## Budget Manager ### //
    // ##################### //
    uiInterface.InitMessage(_("Loading budget cache..."));

    CBudgetDB budgetdb;
    const bool fDryRun = (chain_active_height <= 0);
    if (!fDryRun) g_budgetman.SetBestHeight(chain_active_height);
    CBudgetDB::ReadResult readResult2 = budgetdb.Read(g_budgetman, fDryRun);

    if (readResult2 == CBudgetDB::FileError)
        LogPrintf("Missing budget cache - budget.dat, will try to recreate\n");
    else if (readResult2 != CBudgetDB::Ok) {
        LogPrintf("Error reading budget.dat - cached data discarded\n");
    }

    // flag our cached items so we send them to our peers
    g_budgetman.ResetSync();
    g_budgetman.ReloadMapSeen();

    // ######################################### //
    // ## Legacy Masternodes-Payments Manager ## //
    // ######################################### //
    uiInterface.InitMessage(_("Loading masternode payment cache..."));

    CMasternodePaymentDB mnpayments;
    CMasternodePaymentDB::ReadResult readResult3 = mnpayments.Read(masternodePayments);
    if (readResult3 == CMasternodePaymentDB::FileError)
        LogPrintf("Missing masternode payment cache - mnpayments.dat, will try to recreate\n");
    else if (readResult3 != CMasternodePaymentDB::Ok) {
        LogPrintf("Error reading mnpayments.dat - cached data discarded\n");
    }

    // ############################## //
    // ## Net MNs Metadata Manager ## //
    // ############################## //
    bool fLoadCacheFiles = !(fReindex || fReindexChainState);
    fs::path pathDB = GetDataDir();
    uiInterface.InitMessage(_("Loading masternode cache..."));
    CFlatDB<CMasternodeMetaMan> metadb(MN_META_CACHE_FILENAME, MN_META_CACHE_FILE_ID);
    if (fLoadCacheFiles) {
        if (!metadb.Load(g_mmetaman)) {
            return UIError(strprintf(_("Failed to load masternode metadata cache from: %s"), metadb.GetDbPath().string()));
        }
    } else {
        CMasternodeMetaMan mmetamanTmp;
        if (!metadb.Dump(mmetamanTmp)) {
            return UIError(strprintf(_("Failed to clear masternode metadata cache at: %s"), metadb.GetDbPath().string()));
        }
    }

    return true;
}

void RegisterTierTwoValidationInterface()
{
    RegisterValidationInterface(&g_budgetman);
    RegisterValidationInterface(&masternodePayments);
    if (activeMasternodeManager) RegisterValidationInterface(activeMasternodeManager);
}

void DumpTierTwo()
{
    DumpMasternodes();
    DumpBudgets(g_budgetman);
    DumpMasternodePayments();
    CFlatDB<CMasternodeMetaMan>("mnmetacache.dat", "magicMasternodeMetaCache").Dump(g_mmetaman);
}

void SetBudgetFinMode(const std::string& mode)
{
    g_budgetman.strBudgetMode = mode;
    LogPrintf("Budget Mode %s\n", g_budgetman.strBudgetMode);
}

bool InitActiveMN()
{
    fMasterNode = gArgs.GetBoolArg("-masternode", DEFAULT_MASTERNODE);
    if ((fMasterNode || masternodeConfig.getCount() > -1) && fTxIndex == false) {
        return UIError(strprintf(_("Enabling Masternode support requires turning on transaction indexing."
                                   "Please add %s to your configuration and start with %s"), "txindex=1", "-reindex"));
    }

    if (fMasterNode) {

        if (gArgs.IsArgSet("-connect") && gArgs.GetArgs("-connect").size() > 0) {
            return UIError(_("Cannot be a masternode and only connect to specific nodes"));
        }

        const std::string& mnoperatorkeyStr = gArgs.GetArg("-mnoperatorprivatekey", "");
        const bool fDeterministic = !mnoperatorkeyStr.empty();
        LogPrintf("IS %s MASTERNODE\n", (fDeterministic ? "DETERMINISTIC " : ""));

        if (fDeterministic) {
            // Check enforcement
            if (!deterministicMNManager->IsDIP3Enforced()) {
                const std::string strError = strprintf(
                        _("Cannot start deterministic masternode before enforcement. Remove %s to start as legacy masternode"),
                        "-mnoperatorprivatekey");
                LogPrintf("-- ERROR: %s\n", strError);
                return UIError(strError);
            }
            // Create and register activeMasternodeManager
            activeMasternodeManager = new CActiveDeterministicMasternodeManager();
            auto res = activeMasternodeManager->SetOperatorKey(mnoperatorkeyStr);
            if (!res) { return UIError(res.getError()); }
            // Init active masternode
            const CBlockIndex* pindexTip = WITH_LOCK(cs_main, return chainActive.Tip(););
            activeMasternodeManager->Init(pindexTip);
        } else {
            // Check enforcement
            if (deterministicMNManager->LegacyMNObsolete()) {
                const std::string strError = strprintf(
                        _("Legacy masternode system disabled. Use %s to start as deterministic masternode"),
                        "-mnoperatorprivatekey");
                LogPrintf("-- ERROR: %s\n", strError);
                return UIError(strError);
            }
            auto res = initMasternode(gArgs.GetArg("-masternodeprivkey", ""), gArgs.GetArg("-masternodeaddr", ""),
                                      true);
            if (!res) { return UIError(res.getError()); }
        }
    }

#ifdef ENABLE_WALLET
    // !TODO: remove after complete transition to DMN
    // use only the first wallet here. This section can be removed after transition to DMN
    if (gArgs.GetBoolArg("-mnconflock", DEFAULT_MNCONFLOCK) && !vpwallets.empty() && vpwallets[0]) {
        LOCK(vpwallets[0]->cs_wallet);
        LogPrintf("Locking Masternodes collateral utxo:\n");
        uint256 mnTxHash;
        for (const auto& mne : masternodeConfig.getEntries()) {
            mnTxHash.SetHex(mne.getTxHash());
            COutPoint outpoint = COutPoint(mnTxHash, (unsigned int) std::stoul(mne.getOutputIndex()));
            vpwallets[0]->LockCoin(outpoint);
            LogPrintf("Locked collateral, MN: %s, tx hash: %s, output index: %s\n",
                      mne.getAlias(), mne.getTxHash(), mne.getOutputIndex());
        }
    }

    // automatic lock for DMN
    if (gArgs.GetBoolArg("-mnconflock", DEFAULT_MNCONFLOCK)) {
        LogPrintf("Locking masternode collaterals...\n");
        const auto& mnList = deterministicMNManager->GetListAtChainTip();
        mnList.ForEachMN(false, [&](const CDeterministicMNCPtr& dmn) {
            for (CWallet* pwallet : vpwallets) {
                pwallet->LockOutpointIfMineWithMutex(nullptr, dmn->collateralOutpoint);
            }
        });
    }
#endif
    // All good
    return true;
}

void StartTierTwoThreadsAndScheduleJobs(boost::thread_group& threadGroup, CScheduler& scheduler)
{
    threadGroup.create_thread(std::bind(&ThreadCheckMasternodes));

    // Start LLMQ system
    if (gArgs.GetBoolArg("-disabledkg", false)) {
        if (Params().NetworkIDString() == CBaseChainParams::MAIN) {
            throw std::runtime_error("DKG system can be disabled only on testnet/regtest");
        } else {
            LogPrintf("DKG system disabled.\n");
        }
    } else {
        llmq::StartLLMQSystem();
    }
}

void StopTierTwoThreads()
{
    llmq::StopLLMQSystem();
}

void DeleteTierTwo()
{
    llmq::DestroyLLMQSystem();
    deterministicMNManager.reset();
    evoDb.reset();
}
<commit_msg>init: Validate "-maxconnections" value if the node is a Masternode.<commit_after>// Copyright (c) 2021 The PIVX developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or https://www.opensource.org/licenses/mit-license.php.

#include "tiertwo/init.h"

#include "budget/budgetdb.h"
#include "evo/evodb.h"
#include "flatdb.h"
#include "guiinterface.h"
#include "guiinterfaceutil.h"
#include "masternodeman.h"
#include "masternode-payments.h"
#include "masternodeconfig.h"
#include "llmq/quorums_init.h"
#include "tiertwo/masternode_meta_manager.h"
#include "validation.h"
#include "wallet/wallet.h"

#include <boost/thread.hpp>

std::string GetTierTwoHelpString(bool showDebug)
{
    std::string strUsage = HelpMessageGroup("Masternode options:");
    strUsage += HelpMessageOpt("-masternode=<n>", strprintf("Enable the client to act as a masternode (0-1, default: %u)", DEFAULT_MASTERNODE));
    strUsage += HelpMessageOpt("-mnconf=<file>", strprintf("Specify masternode configuration file (default: %s)", PIVX_MASTERNODE_CONF_FILENAME));
    strUsage += HelpMessageOpt("-mnconflock=<n>", strprintf("Lock masternodes from masternode configuration file (default: %u)", DEFAULT_MNCONFLOCK));
    strUsage += HelpMessageOpt("-masternodeprivkey=<n>", "Set the masternode private key");
    strUsage += HelpMessageOpt("-masternodeaddr=<n>", strprintf("Set external address:port to get to this masternode (example: %s)", "128.127.106.235:51472"));
    strUsage += HelpMessageOpt("-budgetvotemode=<mode>", "Change automatic finalized budget voting behavior. mode=auto: Vote for only exact finalized budget match to my generated budget. (string, default: auto)");
    strUsage += HelpMessageOpt("-mnoperatorprivatekey=<WIF>", "Set the masternode operator private key. Only valid with -masternode=1. When set, the masternode acts as a deterministic masternode.");
    if (showDebug) {
        strUsage += HelpMessageOpt("-pushversion", strprintf("Modifies the mnauth serialization if the version is lower than %d."
                                                             "testnet/regtest only; ", MNAUTH_NODE_VER_VERSION));
        strUsage += HelpMessageOpt("-disabledkg", "Disable the DKG sessions process threads for the entire lifecycle. testnet/regtest only.");
    }
    return strUsage;
}

void InitTierTwoPreChainLoad(bool fReindex)
{
    int64_t nEvoDbCache = 1024 * 1024 * 16; // TODO
    deterministicMNManager.reset();
    evoDb.reset();
    evoDb.reset(new CEvoDB(nEvoDbCache, false, fReindex));
    deterministicMNManager.reset(new CDeterministicMNManager(*evoDb));
}

void InitTierTwoPostCoinsCacheLoad()
{
    // Initialize LLMQ system
    llmq::InitLLMQSystem(*evoDb);
}

// Sets the last CACHED_BLOCK_HASHES hashes into masternode manager cache
static void LoadBlockHashesCache(CMasternodeMan& man)
{
    LOCK(cs_main);
    const CBlockIndex* pindex = chainActive.Tip();
    unsigned int inserted = 0;
    while (pindex && inserted < CACHED_BLOCK_HASHES) {
        man.CacheBlockHash(pindex);
        pindex = pindex->pprev;
        ++inserted;
    }
}

bool LoadTierTwo(int chain_active_height, bool fReindexChainState)
{
    // ################################# //
    // ## Legacy Masternodes Manager ### //
    // ################################# //
    uiInterface.InitMessage(_("Loading masternode cache..."));

    mnodeman.SetBestHeight(chain_active_height);
    LoadBlockHashesCache(mnodeman);
    CMasternodeDB mndb;
    CMasternodeDB::ReadResult readResult = mndb.Read(mnodeman);
    if (readResult == CMasternodeDB::FileError)
        LogPrintf("Missing masternode cache file - mncache.dat, will try to recreate\n");
    else if (readResult != CMasternodeDB::Ok) {
        LogPrintf("Error reading mncache.dat - cached data discarded\n");
    }

    // ##################### //
    // ## Budget Manager ### //
    // ##################### //
    uiInterface.InitMessage(_("Loading budget cache..."));

    CBudgetDB budgetdb;
    const bool fDryRun = (chain_active_height <= 0);
    if (!fDryRun) g_budgetman.SetBestHeight(chain_active_height);
    CBudgetDB::ReadResult readResult2 = budgetdb.Read(g_budgetman, fDryRun);

    if (readResult2 == CBudgetDB::FileError)
        LogPrintf("Missing budget cache - budget.dat, will try to recreate\n");
    else if (readResult2 != CBudgetDB::Ok) {
        LogPrintf("Error reading budget.dat - cached data discarded\n");
    }

    // flag our cached items so we send them to our peers
    g_budgetman.ResetSync();
    g_budgetman.ReloadMapSeen();

    // ######################################### //
    // ## Legacy Masternodes-Payments Manager ## //
    // ######################################### //
    uiInterface.InitMessage(_("Loading masternode payment cache..."));

    CMasternodePaymentDB mnpayments;
    CMasternodePaymentDB::ReadResult readResult3 = mnpayments.Read(masternodePayments);
    if (readResult3 == CMasternodePaymentDB::FileError)
        LogPrintf("Missing masternode payment cache - mnpayments.dat, will try to recreate\n");
    else if (readResult3 != CMasternodePaymentDB::Ok) {
        LogPrintf("Error reading mnpayments.dat - cached data discarded\n");
    }

    // ############################## //
    // ## Net MNs Metadata Manager ## //
    // ############################## //
    bool fLoadCacheFiles = !(fReindex || fReindexChainState);
    fs::path pathDB = GetDataDir();
    uiInterface.InitMessage(_("Loading masternode cache..."));
    CFlatDB<CMasternodeMetaMan> metadb(MN_META_CACHE_FILENAME, MN_META_CACHE_FILE_ID);
    if (fLoadCacheFiles) {
        if (!metadb.Load(g_mmetaman)) {
            return UIError(strprintf(_("Failed to load masternode metadata cache from: %s"), metadb.GetDbPath().string()));
        }
    } else {
        CMasternodeMetaMan mmetamanTmp;
        if (!metadb.Dump(mmetamanTmp)) {
            return UIError(strprintf(_("Failed to clear masternode metadata cache at: %s"), metadb.GetDbPath().string()));
        }
    }

    return true;
}

void RegisterTierTwoValidationInterface()
{
    RegisterValidationInterface(&g_budgetman);
    RegisterValidationInterface(&masternodePayments);
    if (activeMasternodeManager) RegisterValidationInterface(activeMasternodeManager);
}

void DumpTierTwo()
{
    DumpMasternodes();
    DumpBudgets(g_budgetman);
    DumpMasternodePayments();
    CFlatDB<CMasternodeMetaMan>("mnmetacache.dat", "magicMasternodeMetaCache").Dump(g_mmetaman);
}

void SetBudgetFinMode(const std::string& mode)
{
    g_budgetman.strBudgetMode = mode;
    LogPrintf("Budget Mode %s\n", g_budgetman.strBudgetMode);
}

bool InitActiveMN()
{
    fMasterNode = gArgs.GetBoolArg("-masternode", DEFAULT_MASTERNODE);
    if ((fMasterNode || masternodeConfig.getCount() > -1) && fTxIndex == false) {
        return UIError(strprintf(_("Enabling Masternode support requires turning on transaction indexing."
                                   "Please add %s to your configuration and start with %s"), "txindex=1", "-reindex"));
    }

    if (fMasterNode) {

        if (gArgs.IsArgSet("-connect") && gArgs.GetArgs("-connect").size() > 0) {
            return UIError(_("Cannot be a masternode and only connect to specific nodes"));
        }

        if (gArgs.GetArg("-maxconnections", DEFAULT_MAX_PEER_CONNECTIONS) < DEFAULT_MAX_PEER_CONNECTIONS) {
            return UIError(strprintf(_("Masternode must be able to handle at least %d connections, set %s=%d"),
                                     DEFAULT_MAX_PEER_CONNECTIONS, "-maxconnections", DEFAULT_MAX_PEER_CONNECTIONS));
        }

        const std::string& mnoperatorkeyStr = gArgs.GetArg("-mnoperatorprivatekey", "");
        const bool fDeterministic = !mnoperatorkeyStr.empty();
        LogPrintf("IS %s MASTERNODE\n", (fDeterministic ? "DETERMINISTIC " : ""));

        if (fDeterministic) {
            // Check enforcement
            if (!deterministicMNManager->IsDIP3Enforced()) {
                const std::string strError = strprintf(
                        _("Cannot start deterministic masternode before enforcement. Remove %s to start as legacy masternode"),
                        "-mnoperatorprivatekey");
                LogPrintf("-- ERROR: %s\n", strError);
                return UIError(strError);
            }
            // Create and register activeMasternodeManager
            activeMasternodeManager = new CActiveDeterministicMasternodeManager();
            auto res = activeMasternodeManager->SetOperatorKey(mnoperatorkeyStr);
            if (!res) { return UIError(res.getError()); }
            // Init active masternode
            const CBlockIndex* pindexTip = WITH_LOCK(cs_main, return chainActive.Tip(););
            activeMasternodeManager->Init(pindexTip);
        } else {
            // Check enforcement
            if (deterministicMNManager->LegacyMNObsolete()) {
                const std::string strError = strprintf(
                        _("Legacy masternode system disabled. Use %s to start as deterministic masternode"),
                        "-mnoperatorprivatekey");
                LogPrintf("-- ERROR: %s\n", strError);
                return UIError(strError);
            }
            auto res = initMasternode(gArgs.GetArg("-masternodeprivkey", ""), gArgs.GetArg("-masternodeaddr", ""),
                                      true);
            if (!res) { return UIError(res.getError()); }
        }
    }

#ifdef ENABLE_WALLET
    // !TODO: remove after complete transition to DMN
    // use only the first wallet here. This section can be removed after transition to DMN
    if (gArgs.GetBoolArg("-mnconflock", DEFAULT_MNCONFLOCK) && !vpwallets.empty() && vpwallets[0]) {
        LOCK(vpwallets[0]->cs_wallet);
        LogPrintf("Locking Masternodes collateral utxo:\n");
        uint256 mnTxHash;
        for (const auto& mne : masternodeConfig.getEntries()) {
            mnTxHash.SetHex(mne.getTxHash());
            COutPoint outpoint = COutPoint(mnTxHash, (unsigned int) std::stoul(mne.getOutputIndex()));
            vpwallets[0]->LockCoin(outpoint);
            LogPrintf("Locked collateral, MN: %s, tx hash: %s, output index: %s\n",
                      mne.getAlias(), mne.getTxHash(), mne.getOutputIndex());
        }
    }

    // automatic lock for DMN
    if (gArgs.GetBoolArg("-mnconflock", DEFAULT_MNCONFLOCK)) {
        LogPrintf("Locking masternode collaterals...\n");
        const auto& mnList = deterministicMNManager->GetListAtChainTip();
        mnList.ForEachMN(false, [&](const CDeterministicMNCPtr& dmn) {
            for (CWallet* pwallet : vpwallets) {
                pwallet->LockOutpointIfMineWithMutex(nullptr, dmn->collateralOutpoint);
            }
        });
    }
#endif
    // All good
    return true;
}

void StartTierTwoThreadsAndScheduleJobs(boost::thread_group& threadGroup, CScheduler& scheduler)
{
    threadGroup.create_thread(std::bind(&ThreadCheckMasternodes));

    // Start LLMQ system
    if (gArgs.GetBoolArg("-disabledkg", false)) {
        if (Params().NetworkIDString() == CBaseChainParams::MAIN) {
            throw std::runtime_error("DKG system can be disabled only on testnet/regtest");
        } else {
            LogPrintf("DKG system disabled.\n");
        }
    } else {
        llmq::StartLLMQSystem();
    }
}

void StopTierTwoThreads()
{
    llmq::StopLLMQSystem();
}

void DeleteTierTwo()
{
    llmq::DestroyLLMQSystem();
    deterministicMNManager.reset();
    evoDb.reset();
}
<|endoftext|>