Merge branch 'master' of github.com:cryptonomex/graphene
This commit is contained in:
commit
98e761c9c2
22 changed files with 311 additions and 41 deletions
|
|
@ -82,7 +82,6 @@ object_id_type account_create_evaluator::do_apply( const account_create_operatio
|
|||
obj.options = o.options;
|
||||
});
|
||||
|
||||
const auto& global_properties = db().get_global_properties();
|
||||
const auto& dynamic_properties = db().get_dynamic_global_properties();
|
||||
db().modify(dynamic_properties, [](dynamic_global_property_object& p) {
|
||||
++p.accounts_registered_this_interval;
|
||||
|
|
|
|||
|
|
@ -73,14 +73,4 @@ node_property_object& database::node_properties()
|
|||
return _node_property_object;
|
||||
}
|
||||
|
||||
double database::witness_participation_rate()const
|
||||
{
|
||||
if( head_block_num() < 10 ) return 1; // sample size is too small
|
||||
uint32_t produced = std::min<uint32_t>( head_block_num()-1, 100 );
|
||||
auto prior = fetch_block_by_number( head_block_num() - produced );
|
||||
auto delta_time = head_block_time() - prior->timestamp;
|
||||
auto expected_slots = delta_time.to_seconds() / get_global_properties().parameters.block_interval;
|
||||
return double(produced) / expected_slots;
|
||||
}
|
||||
|
||||
} }
|
||||
|
|
|
|||
|
|
@ -525,6 +525,8 @@ void database::init_genesis(const genesis_state_type& genesis_state)
|
|||
_wso.scheduler.produce_schedule(rng);
|
||||
|
||||
_wso.last_scheduling_block = 0;
|
||||
|
||||
_wso.recent_slots_filled = fc::uint128::max_value();
|
||||
});
|
||||
assert( wso.id == witness_schedule_id_type() );
|
||||
|
||||
|
|
|
|||
|
|
@ -141,6 +141,16 @@ void database::update_witness_schedule(const signed_block& next_block)
|
|||
memcpy(_wso.rng_seed.begin(), dpo.random.data(), dpo.random.data_size());
|
||||
}
|
||||
_wso.last_scheduling_block = next_block.block_num();
|
||||
_wso.recent_slots_filled = (
|
||||
(_wso.recent_slots_filled << 1)
|
||||
+ 1) << (schedule_slot - 1);
|
||||
});
|
||||
}
|
||||
|
||||
uint32_t database::witness_participation_rate()const
|
||||
{
|
||||
const witness_schedule_object& wso = get(witness_schedule_id_type());
|
||||
return uint64_t(GRAPHENE_100_PERCENT) * wso.recent_slots_filled.popcount() / 128;
|
||||
}
|
||||
|
||||
} }
|
||||
|
|
|
|||
|
|
@ -138,9 +138,9 @@ namespace graphene { namespace chain {
|
|||
|
||||
/**
|
||||
* Calculate the percent of block production slots that were missed in the
|
||||
* past 100 blocks.
|
||||
* past 128 blocks, not including the current block.
|
||||
*/
|
||||
double witness_participation_rate()const;
|
||||
uint32_t witness_participation_rate()const;
|
||||
|
||||
void add_checkpoints( const flat_map<uint32_t,block_id_type>& checkpts );
|
||||
const flat_map<uint32_t,block_id_type> get_checkpoints()const { return _checkpoints; }
|
||||
|
|
|
|||
|
|
@ -16,6 +16,8 @@
|
|||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#pragma once
|
||||
#include <fc/uint128.hpp>
|
||||
|
||||
#include <graphene/chain/protocol/chain_parameters.hpp>
|
||||
#include <graphene/chain/database.hpp>
|
||||
#include <graphene/db/object.hpp>
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
// needed to serialize witness_scheduler
|
||||
#include <fc/container/deque.hpp>
|
||||
#include <fc/uint128.hpp>
|
||||
|
||||
#include <graphene/chain/protocol/types.hpp>
|
||||
#include <graphene/chain/witness_scheduler.hpp>
|
||||
|
|
@ -57,6 +58,12 @@ class witness_schedule_object : public abstract_object<witness_schedule_object>
|
|||
uint32_t last_scheduling_block;
|
||||
uint64_t slots_since_genesis = 0;
|
||||
fc::array< char, sizeof(secret_hash_type) > rng_seed;
|
||||
|
||||
/**
|
||||
* Not necessary for consensus, but used for figuring out the participation rate.
|
||||
* The nth bit is 0 if the nth slot was unfilled, else it is 1.
|
||||
*/
|
||||
fc::uint128 recent_slots_filled;
|
||||
};
|
||||
|
||||
} }
|
||||
|
|
@ -77,4 +84,5 @@ FC_REFLECT_DERIVED( graphene::chain::witness_schedule_object, (graphene::chain::
|
|||
(last_scheduling_block)
|
||||
(slots_since_genesis)
|
||||
(rng_seed)
|
||||
(recent_slots_filled)
|
||||
)
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
Subproject commit 0391665471b4dffb7af951853a777565a7ae9a74
|
||||
Subproject commit 5f43c06bae6d03e319dd2f230fe7cbd74399a773
|
||||
|
|
@ -57,7 +57,7 @@ private:
|
|||
boost::program_options::variables_map _options;
|
||||
bool _production_enabled = false;
|
||||
bool _consecutive_production_enabled = false;
|
||||
int _required_witness_participation = 33;
|
||||
uint32_t _required_witness_participation = 33 * GRAPHENE_1_PERCENT;
|
||||
|
||||
std::map<chain::public_key_type, fc::ecc::private_key> _private_keys;
|
||||
std::set<chain::witness_id_type> _witnesses;
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ void witness_plugin::plugin_set_program_options(
|
|||
string witness_id_example = fc::json::to_string(chain::witness_id_type());
|
||||
command_line_options.add_options()
|
||||
("enable-stale-production", bpo::bool_switch()->notifier([this](bool e){_production_enabled = e;}), "Enable block production, even if the chain is stale.")
|
||||
("required-participation", bpo::bool_switch()->notifier([this](int e){_required_witness_participation = e;}), "Percent of witnesses (0-99) that must be participating in order to produce blocks")
|
||||
("required-participation", bpo::bool_switch()->notifier([this](int e){_required_witness_participation = uint32_t(e*GRAPHENE_1_PERCENT);}), "Percent of witnesses (0-99) that must be participating in order to produce blocks")
|
||||
("allow-consecutive", bpo::bool_switch()->notifier([this](bool e){_consecutive_production_enabled = e;}), "Allow block production, even if the last block was produced by the same witness.")
|
||||
("witness-id,w", bpo::value<vector<string>>()->composing()->multitoken(),
|
||||
("ID of witness controlled by this node (e.g. " + witness_id_example + ", quotes are required, may specify multiple times)").c_str())
|
||||
|
|
@ -191,11 +191,11 @@ void witness_plugin::block_production_loop()
|
|||
return false;
|
||||
}
|
||||
|
||||
double prate = db.witness_participation_rate();
|
||||
if( int(100*prate) < _required_witness_participation )
|
||||
uint32_t prate = db.witness_participation_rate();
|
||||
if( prate < _required_witness_participation )
|
||||
{
|
||||
elog("Not producing block because node appers to be on a minority fork with only ${x}% witness participation",
|
||||
("x",uint32_t(100*prate) ) );
|
||||
("x",uint32_t(100*uint64_t(prate) / GRAPHENE_1_PERCENT) ) );
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -11,14 +11,25 @@
|
|||
#include <fc/thread/thread.hpp>
|
||||
#include <graphene/app/api.hpp>
|
||||
|
||||
#include <QCryptographicHash>
|
||||
#include <QObject>
|
||||
#include <QQmlListProperty>
|
||||
#include <QtQml>
|
||||
|
||||
using boost::multi_index_container;
|
||||
using namespace boost::multi_index;
|
||||
|
||||
Q_DECLARE_METATYPE(std::function<void()>)
|
||||
|
||||
class Crypto {
|
||||
Q_GADGET
|
||||
|
||||
public:
|
||||
Q_INVOKABLE QString sha256(QByteArray data) {
|
||||
return QCryptographicHash::hash(data, QCryptographicHash::Sha256).toHex();
|
||||
}
|
||||
};
|
||||
QML_DECLARE_TYPE(Crypto)
|
||||
|
||||
class Asset : public QObject {
|
||||
Q_OBJECT
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@
|
|||
|
||||
#include "ClientDataModel.hpp"
|
||||
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
fc::thread::current().set_name( "main" );
|
||||
|
|
@ -22,6 +21,9 @@ int main(int argc, char *argv[])
|
|||
qmlRegisterType<GrapheneApplication>("Graphene.Client", 0, 1, "GrapheneApplication");
|
||||
|
||||
QQmlApplicationEngine engine;
|
||||
QVariant crypto;
|
||||
crypto.setValue(Crypto());
|
||||
engine.rootContext()->setContextProperty("Crypto", crypto);
|
||||
#ifdef NDEBUG
|
||||
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
|
||||
#else
|
||||
|
|
|
|||
1
programs/light_client/qml/.gitignore
vendored
Normal file
1
programs/light_client/qml/.gitignore
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
*.depends
|
||||
|
|
@ -5,6 +5,7 @@ import QtQuick.Dialogs 1.2
|
|||
Rectangle {
|
||||
id: greySheet
|
||||
state: "HIDDEN"
|
||||
color: Qt.rgba(0, 0, 0, showOpacity)
|
||||
|
||||
property real showOpacity: .5
|
||||
property int animationTime: 300
|
||||
|
|
@ -18,8 +19,11 @@ Rectangle {
|
|||
/// Emitted when closed, following fade-out animation
|
||||
signal closed
|
||||
|
||||
function showForm(formType, closedCallback) {
|
||||
formLoader.sourceComponent = formType
|
||||
function showForm(formType, params, closedCallback) {
|
||||
if (formType.status === Component.Error)
|
||||
console.log(formType.errorString())
|
||||
|
||||
formContainer.data = [formType.createObject(formContainer, params)]
|
||||
if (closedCallback instanceof Function)
|
||||
internal.callback = closedCallback
|
||||
state = "SHOWN"
|
||||
|
|
@ -35,12 +39,12 @@ Rectangle {
|
|||
acceptedButtons: Qt.AllButtons
|
||||
}
|
||||
MouseArea {
|
||||
anchors.fill: formLoader
|
||||
anchors.fill: formContainer
|
||||
acceptedButtons: Qt.AllButtons
|
||||
onClicked: mouse.accepted = true
|
||||
}
|
||||
Loader {
|
||||
id: formLoader
|
||||
Item {
|
||||
id: formContainer
|
||||
anchors.centerIn: parent
|
||||
width: parent.width / 2
|
||||
height: parent.height / 2
|
||||
|
|
@ -51,7 +55,7 @@ Rectangle {
|
|||
name: "HIDDEN"
|
||||
PropertyChanges {
|
||||
target: greySheet
|
||||
color: Qt.rgba(0, 0, 0, 0)
|
||||
opacity: 0
|
||||
enabled: false
|
||||
}
|
||||
StateChangeScript {
|
||||
|
|
@ -63,10 +67,12 @@ Rectangle {
|
|||
StateChangeScript {
|
||||
name: "postHidden"
|
||||
script: {
|
||||
console.log("Post")
|
||||
greySheet.closed()
|
||||
formLoader.sourceComponent = undefined
|
||||
formContainer.data = []
|
||||
if (internal.callback instanceof Function)
|
||||
internal.callback()
|
||||
internal.callback = undefined
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
@ -74,7 +80,7 @@ Rectangle {
|
|||
name: "SHOWN"
|
||||
PropertyChanges {
|
||||
target: greySheet
|
||||
color: Qt.rgba(0, 0, 0, showOpacity)
|
||||
opacity: 1
|
||||
enabled: true
|
||||
}
|
||||
StateChangeScript {
|
||||
|
|
@ -95,22 +101,28 @@ Rectangle {
|
|||
Transition {
|
||||
from: "HIDDEN"
|
||||
to: "SHOWN"
|
||||
ScriptAction { scriptName: "preShown" }
|
||||
ColorAnimation {
|
||||
target: greySheet
|
||||
duration: animationTime
|
||||
SequentialAnimation {
|
||||
ScriptAction { scriptName: "preShown" }
|
||||
PropertyAnimation {
|
||||
target: greySheet
|
||||
property: "opacity"
|
||||
duration: animationTime
|
||||
}
|
||||
ScriptAction { scriptName: "postShown" }
|
||||
}
|
||||
ScriptAction { scriptName: "postShown" }
|
||||
},
|
||||
Transition {
|
||||
from: "SHOWN"
|
||||
to: "HIDDEN"
|
||||
ScriptAction { scriptName: "preHidden" }
|
||||
ColorAnimation {
|
||||
target: greySheet
|
||||
duration: animationTime
|
||||
SequentialAnimation {
|
||||
ScriptAction { scriptName: "preHidden" }
|
||||
PropertyAnimation {
|
||||
target: greySheet
|
||||
property: "opacity"
|
||||
duration: animationTime
|
||||
}
|
||||
ScriptAction { scriptName: "postHidden" }
|
||||
}
|
||||
ScriptAction { scriptName: "postHidden" }
|
||||
}
|
||||
]
|
||||
|
||||
|
|
|
|||
12
programs/light_client/qml/Scaling.qml
Normal file
12
programs/light_client/qml/Scaling.qml
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
pragma Singleton
|
||||
import QtQuick 2.5
|
||||
import QtQuick.Window 2.2
|
||||
|
||||
Item {
|
||||
function mm(millimeters) {
|
||||
return Screen.pixelDensity * millimeters
|
||||
}
|
||||
function cm(centimeters) {
|
||||
return mm(centimeters * 10)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,8 +1,60 @@
|
|||
import QtQuick 2.5
|
||||
import QtQuick.Controls 1.4
|
||||
import QtQuick.Dialogs 1.2
|
||||
import QtQuick.Layouts 1.2
|
||||
|
||||
import "."
|
||||
import "jdenticon/jdenticon-1.0.1.min.js" as Jdenticon
|
||||
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
|
||||
Component.onCompleted: console.log("Made a transfer form")
|
||||
Component.onDestruction: console.log("Destroyed a transfer form")
|
||||
|
||||
Column {
|
||||
anchors.centerIn: parent
|
||||
|
||||
RowLayout {
|
||||
Canvas {
|
||||
id: identicon
|
||||
width: Scaling.cm(2)
|
||||
height: Scaling.cm(2)
|
||||
contextType: "2d"
|
||||
|
||||
onPaint: {
|
||||
if (nameField.text)
|
||||
Jdenticon.draw(identicon, nameField.text)
|
||||
else {
|
||||
var context = identicon.context
|
||||
context.reset()
|
||||
var draw_circle = function(context, x, y, radius) {
|
||||
context.beginPath()
|
||||
context.arc(x, y, radius, 0, 2 * Math.PI, false)
|
||||
context.fillStyle = "rgba(0, 0, 0, 0.1)"
|
||||
context.fill()
|
||||
}
|
||||
var size = Math.min(identicon.height, identicon.width)
|
||||
var centerX = size / 2
|
||||
var centerY = size / 2
|
||||
var radius = size/15
|
||||
draw_circle(context, centerX, centerY, radius)
|
||||
draw_circle(context, 2*radius, 2*radius, radius)
|
||||
draw_circle(context, centerX, 2*radius, radius)
|
||||
draw_circle(context, size - 2*radius, 2*radius, radius)
|
||||
draw_circle(context, size - 2*radius, centerY, radius)
|
||||
draw_circle(context, size - 2*radius, size - 2*radius, radius)
|
||||
draw_circle(context, centerX, size - 2*radius, radius)
|
||||
draw_circle(context, 2*radius, size - 2*radius, radius)
|
||||
draw_circle(context, 2*radius, centerY, radius)
|
||||
}
|
||||
}
|
||||
}
|
||||
TextField {
|
||||
id: nameField
|
||||
Layout.fillWidth: true
|
||||
onTextChanged: identicon.requestPaint()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
18
programs/light_client/qml/jdenticon/jdenticon-1.0.1.min.js
vendored
Executable file
18
programs/light_client/qml/jdenticon/jdenticon-1.0.1.min.js
vendored
Executable file
|
|
@ -0,0 +1,18 @@
|
|||
// Jdenticon 1.0.1 | jdenticon.com | zlib licensed | (c) 2014-2015 Daniel Mester Pirttijärvi
|
||||
/*Alteration to official Jdenticon code: make jdenticon() a variable in this context instead of a property of window*/
|
||||
var jdenticon=function(){function h(){}function n(b,a,c,d){this.h=b;this.i=a;this.k=c;this.f=d}function u(b,a){this.e=b;this.g=a||n.q;b.beginPath()}function r(b,a,c){var d=(b="string"===typeof b?document.querySelector(b):b).getContext("2d");c=Math.min(b.width)*(1-2*(c===t?.08:c));d.save();d.clearRect(0,0,b.width,b.height);d.translate(0|(b.width-c)/2,0|(b.height-c)/2);v(d,a||b.getAttribute("data-jdenticon-hash"),c);d.restore()}function v(b,a,c){function d(b,c,d,e,g){e=e?parseInt(a.charAt(e),16):
|
||||
0;c=c[parseInt(a.charAt(d),16)%c.length];var f;for(d=0;d<g.length;d++)f=new n(g[d][0]*p,g[d][1]*p,p,e++%4),f=new u(b,f),c(f,p,d),f.fill()}function e(a){if(0<=a.indexOf(k))for(var b=0;b<a.length;b++)if(0<=l.indexOf(a[b]))return!0}function g(a){b.fillStyle=m[l[a]].toString()}if(30>c)throw Error("Jdenticon cannot render identicons smaller than 30 pixels.");if(!/^[0-9a-f]{10,}$/i.test(a))throw Error("Invalid hash passed to Jdenticon.");c|=0;for(var p=2*(0|c/8),f=parseInt(a.substr(-7),16)/268435455,m=
|
||||
[h.o(76,76,76),h.m(f,.6),h.o(230,230,230),h.m(f,.8),h.n(f,.4)],l=[],k,f=0;3>f;f++){k=parseInt(a.charAt(8+f),16)%m.length;if(e([0,4])||e([2,3]))k=1;l.push(k)}b.clearRect(0,0,c,c);g(0);d(b,w,2,3,[[1,0],[2,0],[2,3],[1,3],[0,1],[3,1],[3,2],[0,2]]);g(1);d(b,w,4,5,[[0,0],[3,0],[3,3],[0,3]]);g(2);d(b,y,1,null,[[1,1],[2,1],[2,2],[1,2]])}function q(){for(var b,a=document.getElementsByTagName("canvas"),c=0;c<a.length;c++)(b=a[c].getAttribute("data-jdenticon-hash"))&&r(a[c],b)}var t,x=window.jQuery;h.o=function(b,
|
||||
a,c){var d=new h;d.p="rgba("+(b&255)+","+(a&255)+","+(c&255)+","+(void 0===t?1:void 0)+")";return d};h.n=function(b,a){var c=new h;c.p="hsla("+(360*b|0)+",50%,"+(100*a|0)+"%,"+(void 0===t?1:void 0)+")";return c};h.m=function(b,a){return h.n(b,1-[.95,1,1,1,.7,.8,.8][6*b+.5|0]*(1-a))};h.prototype={toString:function(){return this.p}};n.q=new n(0,0,0,0);n.prototype={j:function(b,a,c,d){var e=this.h+this.k,g=this.i+this.k;return 1===this.f?[e-a-(d||0),this.i+b]:2===this.f?[e-b-(c||0),g-a-(d||0)]:3===this.f?
|
||||
[this.h+a,g-b-(c||0)]:[this.h+b,this.i+a]}};u.prototype={c:function(b,a){var c=a?-2:2,d=a?b.length-2:0,e=this.e;e.moveTo.apply(e,this.g.j(b[d],b[d+1]));for(d+=c;d<b.length&&0<=d;d+=c)e.lineTo.apply(e,this.g.j(b[d],b[d+1]));e.closePath()},d:function(b,a,c,d,e){var g=this.e;a=this.g.j(b,a,c,d);b=a[0];a=a[1];var h=c/2*.5522848,f=d/2*.5522848,m=b+c,l=a+d;c=b+c/2;var k=a+d/2;e&&(l=a,a+=d,f=-f);g.moveTo(b,k);g.bezierCurveTo(b,k-f,c-h,a,c,a);g.bezierCurveTo(c+h,a,m,k-f,m,k);g.bezierCurveTo(m,k+f,c+h,l,c,
|
||||
l);g.bezierCurveTo(c-h,l,b,k+f,b,k);g.closePath()},a:function(b,a,c,d,e){this.c([b,a,b+c,a,b+c,a+d,b,a+d],e)},b:function(b,a,c,d,e,g){b=[b+c,a,b+c,a+d,b,a+d,b,a];b.splice((e||0)%4,2);this.c(b,g)},l:function(b,a,c,d,e){this.c([b+c/2,a,b+c,a+d/2,b+c/2,a+d,b,a+d/2],e)},fill:function(){this.e.fill()}};var y=[function(b,a){var c=.42*a;b.c([0,0,a,0,a,a-2*c,a-c,a,0,a])},function(b,a){var c=0|.4*a;b.b(a-c,a-2*c,c,2*c,1)},function(b,a){var c=0|a/3;b.a(c,c,a-c,a-c)},function(b,a){var c=0|.1*a,d=0|.25*a;b.a(d,
|
||||
d,a-c-d,a-c-d)},function(b,a){var c=0|.15*a,d=0|.5*a;b.d(a-d-c,a-d-c,d,d)},function(b,a){var c=.1*a,d=4*c;b.a(0,0,a,a);b.c([d,d,a-c,d,d+(a-d-c)/2,a-c],!0)},function(b,a){b.b(0,0,a,a,0)},function(b,a){b.b(a/2,a/2,a/2,a/2,0)},function(b,a){b.a(0,0,a,a/2);b.a(0,a/2,a/2,a/2);b.b(a/2,a/2,a/2,a/2,1)},function(b,a){var c=0|.14*a,d=0|.35*a;b.a(0,0,a,a);b.a(d,d,a-d-c,a-d-c,!0)},function(b,a){var c=.12*a,d=3*c;b.a(0,0,a,a);b.d(d,d,a-c-d,a-c-d,!0)},function(b,a){b.b(a/2,a/2,a/2,a/2,3)},function(b,a){var c=.25*
|
||||
a;b.a(0,0,a,a);b.l(c,c,a-c,a-c,!0)},function(b,a,c){var d=.4*a;a*=1.2;c||b.d(d,d,a,a)}],w=[function(b,a){b.b(0,0,a,a,0)},function(b,a){b.b(0,a/2,a,a/2,0)},function(b,a){b.l(0,0,a,a)},function(b,a){var c=a/6;b.d(c,c,a-2*c,a-2*c)}];q.drawIcon=v;q.update=r;x&&(x.fn.jdenticon=function(b,a){this.each(function(c,d){r(d,b,a)});return this});/*Alteration to official Jdenticon code: Removed call to schedule a render immediately on load*/return q}();
|
||||
|
||||
// The following functions were added, and are not part of the official Jdenticon code
|
||||
|
||||
/// @param canvas The canvas to draw on
|
||||
/// @param data The data to generate an identicon for (this will be hashed to generate the identicon)
|
||||
function draw(canvas, data) {
|
||||
jdenticon.drawIcon(canvas.context, Crypto.sha256(data), Math.min(canvas.width, canvas.height))
|
||||
}
|
||||
21
programs/light_client/qml/jdenticon/license.txt
Executable file
21
programs/light_client/qml/jdenticon/license.txt
Executable file
|
|
@ -0,0 +1,21 @@
|
|||
|
||||
Jdenticon
|
||||
Copyright (c) 2014 Daniel Mester Pirttijärvi
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
import QtQuick 2.5
|
||||
import QtQuick.Controls 1.4
|
||||
import QtQuick.Dialogs 1.2
|
||||
import QtQuick.Window 2.2
|
||||
|
||||
import Qt.labs.settings 1.0
|
||||
|
||||
|
|
@ -47,9 +48,10 @@ ApplicationWindow {
|
|||
anchors.centerIn: parent
|
||||
Button {
|
||||
text: "Transfer"
|
||||
onClicked: formBox.showForm(Qt.createComponent("TransferForm.qml"), function() {
|
||||
console.log("Closed form")
|
||||
})
|
||||
onClicked: formBox.showForm(Qt.createComponent("TransferForm.qml"), {},
|
||||
function() {
|
||||
console.log("Closed form")
|
||||
})
|
||||
}
|
||||
TextField {
|
||||
id: nameField
|
||||
|
|
@ -80,6 +82,7 @@ ApplicationWindow {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
FormBox {
|
||||
|
|
|
|||
|
|
@ -3,6 +3,8 @@
|
|||
<file>main.qml</file>
|
||||
<file>TransferForm.qml</file>
|
||||
<file>FormBox.qml</file>
|
||||
<file>jdenticon/jdenticon-1.0.1.min.js</file>
|
||||
<file>Scaling.qml</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
||||
|
|
|
|||
1
programs/light_client/qml/qmldir
Normal file
1
programs/light_client/qml/qmldir
Normal file
|
|
@ -0,0 +1 @@
|
|||
singleton Scaling Scaling.qml
|
||||
|
|
@ -907,4 +907,128 @@ BOOST_FIXTURE_TEST_CASE( witness_scheduler_missed_blocks, database_fixture )
|
|||
});
|
||||
} FC_LOG_AND_RETHROW() }
|
||||
|
||||
BOOST_FIXTURE_TEST_CASE( rsf_missed_blocks, database_fixture )
|
||||
{
|
||||
try
|
||||
{
|
||||
generate_block();
|
||||
|
||||
auto rsf = [&]() -> string
|
||||
{
|
||||
fc::uint128 rsf = db.get( witness_schedule_id_type() ).recent_slots_filled;
|
||||
string result = "";
|
||||
result.reserve(128);
|
||||
for( int i=0; i<128; i++ )
|
||||
{
|
||||
result += ((rsf.lo & 1) == 0) ? '0' : '1';
|
||||
rsf >>= 1;
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
auto pct = []( uint32_t x ) -> uint32_t
|
||||
{
|
||||
return uint64_t( GRAPHENE_100_PERCENT ) * x / 128;
|
||||
};
|
||||
|
||||
BOOST_CHECK_EQUAL( rsf(),
|
||||
"1111111111111111111111111111111111111111111111111111111111111111"
|
||||
"1111111111111111111111111111111111111111111111111111111111111111"
|
||||
);
|
||||
BOOST_CHECK_EQUAL( db.witness_participation_rate(), GRAPHENE_100_PERCENT );
|
||||
|
||||
generate_block( ~0, init_account_priv_key, 1 );
|
||||
BOOST_CHECK_EQUAL( rsf(),
|
||||
"0111111111111111111111111111111111111111111111111111111111111111"
|
||||
"1111111111111111111111111111111111111111111111111111111111111111"
|
||||
);
|
||||
BOOST_CHECK_EQUAL( db.witness_participation_rate(), pct(127) );
|
||||
|
||||
generate_block( ~0, init_account_priv_key, 1 );
|
||||
BOOST_CHECK_EQUAL( rsf(),
|
||||
"0101111111111111111111111111111111111111111111111111111111111111"
|
||||
"1111111111111111111111111111111111111111111111111111111111111111"
|
||||
);
|
||||
BOOST_CHECK_EQUAL( db.witness_participation_rate(), pct(126) );
|
||||
|
||||
generate_block( ~0, init_account_priv_key, 2 );
|
||||
BOOST_CHECK_EQUAL( rsf(),
|
||||
"0010101111111111111111111111111111111111111111111111111111111111"
|
||||
"1111111111111111111111111111111111111111111111111111111111111111"
|
||||
);
|
||||
BOOST_CHECK_EQUAL( db.witness_participation_rate(), pct(124) );
|
||||
|
||||
generate_block( ~0, init_account_priv_key, 3 );
|
||||
BOOST_CHECK_EQUAL( rsf(),
|
||||
"0001001010111111111111111111111111111111111111111111111111111111"
|
||||
"1111111111111111111111111111111111111111111111111111111111111111"
|
||||
);
|
||||
BOOST_CHECK_EQUAL( db.witness_participation_rate(), pct(121) );
|
||||
|
||||
generate_block( ~0, init_account_priv_key, 5 );
|
||||
BOOST_CHECK_EQUAL( rsf(),
|
||||
"0000010001001010111111111111111111111111111111111111111111111111"
|
||||
"1111111111111111111111111111111111111111111111111111111111111111"
|
||||
);
|
||||
BOOST_CHECK_EQUAL( db.witness_participation_rate(), pct(116) );
|
||||
|
||||
generate_block( ~0, init_account_priv_key, 8 );
|
||||
BOOST_CHECK_EQUAL( rsf(),
|
||||
"0000000010000010001001010111111111111111111111111111111111111111"
|
||||
"1111111111111111111111111111111111111111111111111111111111111111"
|
||||
);
|
||||
BOOST_CHECK_EQUAL( db.witness_participation_rate(), pct(108) );
|
||||
|
||||
generate_block( ~0, init_account_priv_key, 13 );
|
||||
BOOST_CHECK_EQUAL( rsf(),
|
||||
"0000000000000100000000100000100010010101111111111111111111111111"
|
||||
"1111111111111111111111111111111111111111111111111111111111111111"
|
||||
);
|
||||
BOOST_CHECK_EQUAL( db.witness_participation_rate(), pct(95) );
|
||||
|
||||
generate_block();
|
||||
BOOST_CHECK_EQUAL( rsf(),
|
||||
"1000000000000010000000010000010001001010111111111111111111111111"
|
||||
"1111111111111111111111111111111111111111111111111111111111111111"
|
||||
);
|
||||
BOOST_CHECK_EQUAL( db.witness_participation_rate(), pct(95) );
|
||||
|
||||
generate_block();
|
||||
BOOST_CHECK_EQUAL( rsf(),
|
||||
"1100000000000001000000001000001000100101011111111111111111111111"
|
||||
"1111111111111111111111111111111111111111111111111111111111111111"
|
||||
);
|
||||
BOOST_CHECK_EQUAL( db.witness_participation_rate(), pct(95) );
|
||||
|
||||
generate_block();
|
||||
BOOST_CHECK_EQUAL( rsf(),
|
||||
"1110000000000000100000000100000100010010101111111111111111111111"
|
||||
"1111111111111111111111111111111111111111111111111111111111111111"
|
||||
);
|
||||
BOOST_CHECK_EQUAL( db.witness_participation_rate(), pct(95) );
|
||||
|
||||
generate_block();
|
||||
BOOST_CHECK_EQUAL( rsf(),
|
||||
"1111000000000000010000000010000010001001010111111111111111111111"
|
||||
"1111111111111111111111111111111111111111111111111111111111111111"
|
||||
);
|
||||
BOOST_CHECK_EQUAL( db.witness_participation_rate(), pct(95) );
|
||||
|
||||
generate_block( ~0, init_account_priv_key, 64 );
|
||||
BOOST_CHECK_EQUAL( rsf(),
|
||||
"0000000000000000000000000000000000000000000000000000000000000000"
|
||||
"1111100000000000001000000001000001000100101011111111111111111111"
|
||||
);
|
||||
BOOST_CHECK_EQUAL( db.witness_participation_rate(), pct(31) );
|
||||
|
||||
generate_block( ~0, init_account_priv_key, 32 );
|
||||
BOOST_CHECK_EQUAL( rsf(),
|
||||
"0000000000000000000000000000000010000000000000000000000000000000"
|
||||
"0000000000000000000000000000000001111100000000000001000000001000"
|
||||
);
|
||||
BOOST_CHECK_EQUAL( db.witness_participation_rate(), pct(8) );
|
||||
}
|
||||
FC_LOG_AND_RETHROW()
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
|
|
|
|||
Loading…
Reference in a new issue