Implementation of jurisdictional agility in BEOS blockchain

in #blockchain5 years ago (edited)

Preface: A while back I made an introductory post that described how jurisdictional agility (the ability for blockchain users to choose in which jurisdiction their transaction takes place within a geographically distributed network) functions on the BEOS blockchain. This is a follow-up post that describes how this functionality is implemented in BEOS and is primarily intended for a technical audience (blockchain architects and programmers).

Management of block producer jurisdictions in BEOS

BEOS block producers can publish the regions (one or more jurisdictions) in which they are located, and users can specify one or more jurisdictional regions in which their transaction is to be processed.

A BEOS jurisdiction is defined by a unique id code (uint16), a unique name (a lowercase string of less than 256 characters), and a description (a string of less than 256 characters). Jurisdictions are stored as blockchain state data in two C++ multi-indexes: jurisdiction_dictionary_object and jurisdiction_producer_object.

BEOS has a default list of jurisdictions for countries based on ISO 3166 country codes plus the European Union (code 10000) and International Waters (code 10001). Additional jurisdictions can be created by “burning” 1000 BEOS (paid to eosio.null).

The blockchain software for jurisdictional agility does not know anything about logical associations between jurisdictions. For example, the blockchain does not know that Warsaw is located in Poland. So a block producer (BP) must separately publish that it is in Warsaw, Poland, and the European Union in order to be able to process transactions destined for all three of these jurisdictions.

A BP can change its jurisdictions in two ways: 1) directly calling the updateprod action on the eosio.system contract with its set of jurisdiction codes or 2) by calling the update_jurisdictions action defined in the optional gps plugin. This latter method allows a mobile BP (e.g. a block producer on a ship) to use a gps receiver to get its current coordinates then call update_jurisdictions to convert those geo coordinates into one or more jurisdictions which contain those coordinates.

If a BP maintains BP nodes in multiple jurisdictions (e.g. a node in the US and a node in China), they should only publish the jurisdiction(s) of the node that will be producing their upcoming block. This adds predictability to users about what jurisdictions are available in the upcoming round of blocks and makes it possible to determine what jurisdiction was used to produce any block based solely on the jurisdiction history published by the block producers.

eosio.system contract actions for managing jurisdictions

The eosio.system actions below are called by block producers to add new jurisdictions and specify their jurisdictions.

void addjurisdict( account_name ram_payer, code_jurisdiction new_code, std::string new_name, std::string new_description )
void updateprod( eosio::jurisdiction_producer data )
  • addjurisdict - adds a jurisdiction to the jurisdictions dictionary
  • updateprod - update jurisdictions for given producer
struct jurisdiction_producer {
      account_name                        producer;
      std::vector< code_jurisdiction >    jurisdictions;
};

The eosio.system contract also has special actions that can only be performed by the contract owner. These actions are for blockchain configuration (for example, to configure the initially supported jurisdictions and set the fee for creating new jurisdictions).

void addmultijurs(std::vector<new_jurisdic_info> new_jurisdicts)
void updatejurfee(asset quantity)
void updatejuracc(account_name target_account)

Encoding a Jurisdiction requirement into a BEOS transaction

The class transaction has the data member extensions_type transaction_extensions.

where extensions_type: std::vector<extension_storage>

Description of extension_storage

  • uint16_t - type of data: always 0
  • std::vector - codes of jurisdictions
struct extension_storage
    {
        uint16_t type;
        std::vector<char> data;
    };

If extensions_type is empty, it indicates that the given transaction doesn’t have any required jurisdiction. This is the default behavior.

Jurisdiction API plugin

The new Jurisdiction API Plugin provides the API calls necessary to support jurisdictional agility. It implements the following API calls:

get_active_jurisdictions

This method list all jurisdiction currently available in active producer nodes.

Parameters:

{
  "limit" : 1000
}

limit default value is 1000.

Usage:

  • Get all active jurisdictions
curl -H "CONTENT-TYPE:application/json" --url 127.0.0.1:8888/v1/jurisdiction/get_active_jurisdictions -X POST -d '{}'
  • Get first 100 active jurisdictions
curl -H "CONTENT-TYPE:application/json" --url 127.0.0.1:8888/v1/jurisdiction/get_active_jurisdictions -X POST -d '{"limit" : 100}'

Return:

{
  "jurisdictions":[0]
}

get_producer_jurisdiction

This method lists all jurisdictions for a given producer.

Usage:

curl -H "CONTENT-TYPE:application/json" --url 127.0.0.1:8888/v1/jurisdiction/get_producer_jurisdiction -X POST -d '{"producer_names":["eosio"]}'

Return:

{
  "producer_jurisdictions":[
    {"producer":"eosio","jurisdictions":[0]}
  ]
}

get_all_jurisdictions

This method lists all jurisdiction defined in the system.
Parameters:

{
  "limit" : 1000,
  "last_code" : 50
}

limit and last_code are optional. limit default value is 1000. last_code is to support pagination schemes, you can define a code to start iteration.

Example Usage of API calls:

  • List all jurisdictions up to query limit (1000).
curl -H "CONTENT-TYPE:application/json" --url 127.0.0.1:8888/v1/jurisdiction/get_all_jurisdictions -X POST -d '{}'
  • List all jurisdictions with to query limit set to 100.
curl -H "CONTENT-TYPE:application/json" --url 127.0.0.1:8888/v1/jurisdiction/get_all_jurisdictions -X POST -d '{"limit":100}'
  • List all jurisdictions with to query limit set to 100 starting from code 50.
curl -H "CONTENT-TYPE:application/json" --url 127.0.0.1:8888/v1/jurisdiction/get_all_jurisdictions -X POST -d '{"limit":100, "last_code" : 50}'

Return:

{
  "jurisdictions":[
    {"code":50,"name":"poland","description":"EAST EUROPE"},
    {"code":51,"name":"germany","description":"EAST EUROPE"}
  ]
}

New jurisdiction history API plugin

This optional plugin was added to track jurisdiction changes by block producers. It is not required for a node that only acts as a block producer, but it should be enabled for an API node.

To enable the jurisdiction history for block producers, you must add this line to your BEOS node's config.ini:

enable-jurisdiction-history = true

The jurisdiction history API supports the API calls described below:

get_all_producer_jurisdiction_for_block

Returns information about all jurisdictions for every producer for a given block.

Arguments:

{
  "block_number" : 1000 
}

The argument block_number is optional. By default, the current head block is used if no block number is specified.

Returns:

{
    "producer_jurisdiction_for_block": [{
        "producer_name": "beos.proda",
        "block_with_last_change": 143,
        "date_changed": "2019-06-17T13:30:55.500",
        "new_jurisdictions": [1, 2, 3]
    }, {
        "producer_name": "beos.prodb",
        "block_with_last_change": 149,
        "date_changed": "2019-06-17T13:30:58.500",
        "new_jurisdictions": [11, 12, 13]
    }]
}

Curl call example:

curl -H "CONTENT-TYPE:application/json" --url 127.0.0.1:8888/v1/jurisdiction_history/get_all_producer_jurisdiction_for_block -X POST -d '{"block_number":2000}'

get_producer_jurisdiction_for_block

Returns information about the jurisdiction of a given producer for a given block.

Arguments:

{
  "producer" : "eosio",
  "block_number" : 1000
}

Returns:

{
  "producer_jurisdiction_for_block" : [
    {
      "producer_name" : "eosio",
      "block_with_last_change" : 700,
      "date_changed" : "2019-06-07T09:00",
      "new_jurisdictions" : [1,2]
    }
  ]
}

Curl call example:

curl -H "CONTENT-TYPE:application/json" --url 127.0.0.1:8888/v1/jurisdiction_history/get_producer_jurisdiction_for_block -X POST -d '{"producer":"eosio","block_number":1000}'

get_producer_jurisdiction_history

This method returns the jurisdiction changes for a given producer in a given period of time. from_date and to_date are optional. If from_date is not defined, it is set to the beginning of the epoch. If to_date is not defined, it is set to the current time.

Arguments:

{
  "producer" : "eosio",
  "from_date" : "2019-06-07T09:00",
  "to_date" : "2019-06-07T10:00"
  "limit" : 1000
}

limit field is optional, set by default to 1000.

Returns:

{
  "producer_jurisdiction_history" : [
    {
      "producer_name" : "eosio",
      "block_number" : 700,
      "date_changed" : "2019-06-07T09:00",
      "new_jurisdictions" : [1,2]
    },
    {
      "producer_name" : "eosio",
      "block_number" : 1200,
      "date_changed" : "2019-06-07T09:01",
      "new_jurisdictions" : [3]
    },
  ]
}

Curl call example:

  • Get all changes in a given time period.
curl -H "CONTENT-TYPE:application/json" --url 127.0.0.1:8888/v1/jurisdiction_history/get_producer_jurisdiction_history -X POST -d '{"producer":"eosio","from_date":"2019-06-07T09:00","to_date":"2019-06-07T10:00"}'
  • Get first 100 changes in a given time period.
curl -H "CONTENT-TYPE:application/json" --url 127.0.0.1:8888/v1/jurisdiction_history/get_producer_jurisdiction_history -X POST -d '{"producer":"eosio","from_date":"2019-06-07T09:00","to_date":"2019-06-07T10:00", "limit":100}'

CLEOS (command-line wallet) modifications to support jurisdictional agility

A new switch has been added to the wallet command cleos push action/transaction/transactions to define in which jurisdiction transaction(s) should be performed:

  • -u,--jurisdictions TEXT - set allowable jurisdiction codes for the transaction (a maximum of 255 allowable jurisdictions can be specified), default is any

Examples using optional jurisdictions switch

In order to specify in which jurisdiction a transaction should be executed, you need to add the `-u,--jurisdiction switch. Below are some example usages:

./cleos push action --jurisdictions '[0]' eosio.token transfer '[ "xxx", "yyy", "0.0001 BTS", "HI" ]' -p xxx

./cleos push action --u '[0]' eosio.token transfer '[ "xxx", "yyy", "0.0001 BTS", "HI" ]' -p xxx

./cleos push action --jurisdictions '[0,1,2,3,4]' eosio.token transfer '[ "xxx", "yyy", "0.0001 BTS", "HI" ]' -p xxx

./cleos push action --u '[0,1,2,3,4]' eosio.token transfer '[ "xxx", "yyy", "0.0001 BTS", "HI" ]' -p xxx

In the examples above, several sets of allowable jurisdictions have been specified:

  • [0] - this transaction will be executed only in jurisdiction 0,
  • [0,1,2,3,4] - this transaction will be executed in one of the following jurisdictions0,1,2,3,4`.

New get sub-commands

In order to get information about jurisdictions from cleos, several new get sub-commands have been added:

  • all_jurisdictions - Retrieve all jurisdictions from the blockchain,
  • active_jurisdictions - Retrieve active jurisdictions from the blockchain,
  • producer_jurisdiction - Retrieve jurisdictions for given producer from the blockchain,
  • all_producer_jurisdiction_for_block - Retrieve all jurisdictions for all producer in given block from the blockchain,
  • producer_jurisdiction_for_block - Retrieve jurisdictions for producer in given block from the blockchain,
  • producer_jurisdiction_history - Retrieve jurisdictions history for producer from the blockchain.

Command all_jurisdictions

This command will retrieve all jurisdictions from the blockchain, for example:

./cleos get all_jurisdictions

will return:

{
  "jurisdictions":[
    {"code":0,"name":"poland","description":"EAST EUROPE"},
    {"code":1,"name":"germany","description":"EAST EUROPE"}
  ]
}

Command active_jurisdictions

This command will retrieve active jurisdictions from the blockchain, for example:

./cleos get active_jurisdictions

will return:

{
  "jurisdictions":[0]
}

Command producer_jurisdiction

This command will retrieve jurisdictions for given producer from the blockchain, for example:

./cleos get producer_jurisdiction '["eosio"]'

will return:

{
  "producer_jurisdictions":[
    {"producer":"eosio","jurisdictions":[0]}
  ]
}

Command all_producer_jurisdiction_for_block

This command will retrieve all jurisdictions for all producer in given block from the blockchain, for example:

./cleos get all_producer_jurisdiction_for_block "1000"

will return:

{
    "producer_jurisdiction_for_block": [{
        "producer_name": "beos.proda",
        "block_with_last_change": 143,
        "date_changed": "2019-06-17T13:30:55.500",
        "new_jurisdictions": [1, 2, 3]
    }, {
        "producer_name": "beos.prodb",
        "block_with_last_change": 149,
        "date_changed": "2019-06-17T13:30:58.500",
        "new_jurisdictions": [11, 12, 13]
    }]
}

Command producer_jurisdiction_for_block

This command will retrieve jurisdictions for producer in given block from the blockchain, for example:

./cleos get producer_jurisdiction_for_block "eosio" 1000

will return:

{
  "producer_jurisdiction_history" : [
    {
      "producer_name" : "eosio",
      "block_number" : 700,
      "date_changed" : "2019-06-07T09:00",
      "new_jurisdictions" : [1,2]
    },
    {
      "producer_name" : "eosio",
      "block_number" : 1200,
      "date_changed" : "2019-06-07T09:01",
      "new_jurisdictions" : [3]
    },
  ]
}

Command producer_jurisdiction_history

This command will retrieve jurisdictions history for producer from the blockchain, for example:

./cleos get producer_jurisdiction_history "eosio" "2019-06-07T09:00" "2019-06-07T10:00"

will return:

{
  "producer_jurisdiction_history" : [
    {
      "producer_name" : "eosio",
      "block_number" : 700,
      "date_changed" : "2019-06-07T09:00",
      "new_jurisdictions" : [1,2]
    },
    {
      "producer_name" : "eosio",
      "block_number" : 1200,
      "date_changed" : "2019-06-07T09:01",
      "new_jurisdictions" : [3]
    },
  ]
}

Deployed now on BEOS blockchain

All of the above functionalities are fully deployed on the latest version of the BEOS blockchain. Together, they enable both stationary and mobile block producers to publish the current jurisdictions in which they operate and for blockchain users to pick and choose among available jurisdictions to specify where they want their transactions to take place.

The updated blockchain code is located at:
https://github.com/terradacs/beos-core/tree/beos-jurisdiction-dev

Sort:  

This sounds fantastic Dan and we wouldnt expect anything else from such a good dev. I have to admit that im not tecnical enough to understand all of the details, but i love the concept of jurisdictional agility in BEOS.

excellent.. nice

At Build-it we appreciate How-to tutorials, that being said, we heartily appreciate the time and effort @blocktrades spent in publishing this masterpiece, which is why we've curated this article with a 100% vote from our @build-it.curator account.

That being said, in an attempt to pass this useful information to other technologists out there, could you add the #how-to tag to the list of your tag thus getting more eyes on this work.

With mutual respect to @blocktrades from the @build-it team.

Cheers!

Amazing work! I would never be able to think in symbols!!

Amigo aqui mi visita,espero contar con su buen voto y ayuda,soy venezolana y estoy en mi pais todavia soportando esta hambre por falta de dinero,los salarios 2 o 3 dolares mensuales,que es eso?,necesito unas medicinas y por falta de dinero no he comprado esto un caos total todo

Hola @petrarodriguez. Primero que todo, no puedes comentar un post pensando en solo recibir un voto del autor, Steem está más que nada hecho para crear comunidad y comentar un post (en inglés, de hecho) solamente pidiendo votos es algo muy mal visto en la comunidad y no es para nada recomendable. Te invito a que leas el artículo completo (de saber inglés) o que busques otras formas para poder ganar votos (te recomiendo completamente hacer comunidad). ¡Buena suerte!

Any idea when EOS trades will be re-enabled?

We have to reindex our node after the EOS hardfork and reindexing EOS takes quite a while nowadays. Plus, we had a problem during our first reindex, so we had to begin another one (started on 10/10). It's about half way through the reindex now, so I guess it will be up around 10/18.

Okay cool. Thank you!

Posted using Partiko Android