Coder Social home page Coder Social logo

bigchaindb / cryptoconditions Goto Github PK

View Code? Open in Web Editor NEW
72.0 16.0 42.0 322 KB

A Python implementation of the Crypto-Conditions spec

License: MIT License

Python 98.90% Makefile 1.00% Dockerfile 0.09%
crypto-conditions interledger-protocol signed-messages

cryptoconditions's Introduction

Codecov branch Latest release Status on PyPI Travis branch Documentation Status Join the chat at https://gitter.im/bigchaindb/bigchaindb

BigchainDB Server

BigchainDB is the blockchain database. This repository is for BigchainDB Server.

The Basics

Run and Test BigchainDB Server from the master Branch

Running and testing the latest version of BigchainDB Server is easy. Make sure you have a recent version of Docker Compose installed. When you are ready, fire up a terminal and run:

git clone https://github.com/bigchaindb/bigchaindb.git
cd bigchaindb
make run

BigchainDB should be reachable now on http://localhost:9984/.

There are also other commands you can execute:

  • make start: Run BigchainDB from source and daemonize it (stop it with make stop).
  • make stop: Stop BigchainDB.
  • make logs: Attach to the logs.
  • make test: Run all unit and acceptance tests.
  • make test-unit-watch: Run all tests and wait. Every time you change code, tests will be run again.
  • make cov: Check code coverage and open the result in the browser.
  • make doc: Generate HTML documentation and open it in the browser.
  • make clean: Remove all build, test, coverage and Python artifacts.
  • make reset: Stop and REMOVE all containers. WARNING: you will LOSE all data stored in BigchainDB.

To view all commands available, run make.

Links for Everyone

Links for Developers

Legal

cryptoconditions's People

Contributors

chuseuiti avatar codegeschrei avatar davie0 avatar diminator avatar kremalicious avatar muawiakh avatar r-marques avatar sbellem avatar sfstpala avatar ttmc avatar vrde avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

cryptoconditions's Issues

Un-pin requirements in setup.py

See best practices outlined in https://packaging.python.org/requirements/#id5:

It is not considered best practice to use install_requires to pin dependencies to specific versions, or to specify sub-dependencies (i.e. dependencies of your dependencies). This is overly-restrictive, and prevents the user from gaining the benefit of dependency upgrades.

VerifyingKey.verify throws ValueError or AttributeError

For some values VerifyingKey.validate throws ValueError or AttributeError, while it should just return False. As far as I remember, this happened when the signature parameter was out of the expected range of the method, so:

  1. Inputting a non-string
  2. Inputting a non-compliant fulfillment URI ('abc' e.g.)

See how we have to handle this currently in BDB:

Rename ParsingError to ParseError

At least for now now, whenever it makes sense, we mirror the JS reference implementation. That is, for language-independent things.

Investigate what can be done for pynacl dependency on libffi (header file ffi.h)

Carrying this over from bigchaindb/bigchaindb-driver#140, copying here for convenience:

Some questions:

Important note: Although this issue is being created under bigchaindb-driver for the time being, this is something, if possible, that should be pushed down to cryptoconditions, at the very least, and further to pynacl if it makes sense.

Update to version 02 of the draft specification

draft is at https://tools.ietf.org/html/draft-thomas-crypto-conditions-02

Some details to double check for:

  • URI normalization: see issues rfcs/crypto-conditions#8 and rfcs/crypto-conditions#12
  • add condition validation to tests
  • document support for subtypes (which ones) and behaviour of the implementation with respect to unsupported types (types above id 4 are ignored)

Things left to be done

Try to shorten the description in setup.py and on github

The description given in setup.py and on github is quite lengthy. Could we find a way to capture the essence of cryptoconditions in fewer words?

This would be useful when referring to cryptoconditions.

E.g.:

  • python port from the Interledger Protocol (ILP)
  • multi-algorithm, multi-level, multi-signature standard format for expressing conditions and fulfillments
  • multi-signature standard for expressing conditions and fulfillments

Error on long subfulfillments

After adding a certain amount of subconditions, the serializeUri fails:

Test vector attached

Stacktrace

  File "bigchaindb-server/bigchaindb/common/transaction.py", line 904, in
to_dict                                                                                                
    condition['uri'] = self.fulfillment.condition_uri                                                   
  File "cryptoconditions/fulfillment.py", line 154, in condition_uri                                                                             
    return self.condition.serialize_uri()                                                               
  File "cryptoconditions/fulfillment.py", line 142, in condition                                                                                 
    condition.hash = self.generate_hash()                                                               
  File "cryptoconditions/types/base_sha256.py", line 21, in generate_hash                                                                        
    self.write_hash_payload(hasher)                                                                     
  File "cryptoconditions/types/threshold_sha256.py", line 206, in write_hash_payload                                                             
    if c['type'] == FULFILLMENT                                                                         
  File "cryptoconditions/fulfillment.py", line 164, in condition_binary                                                                          
    return self.condition.serialize_binary()                                                            
  File "cryptoconditions/condition.py", line 244, in serialize_binary                                                                            
    writer.write_var_uint(self.max_fulfillment_length)                                                  
  File "cryptoconditions/lib/writer.py", line 50, in write_var_uint                                                                              
    buffer += bytes([value])                                                                            
ValueError: bytes must be in range(0, 256)                                                              

Test vector

{"id":"f018248e7793a9ad69300bcfb600420ceec9ae496a00244f3ac5a65e6d69ee7c","operation":"CREATE","outputs":[{"amount":1,"condition":{"details":{"type_id":2,"type":"fulfillment","bitmask":43,"threshold":2,"subfulfillments":[{"type_id":4,"bitmask":32,"signature":null,"public_key":"79K8SPZbeSDYXBrWgt3dsNmYTZbKNtdYQ5XrjA9XEWfG","type":"fulfillment","weight":1},{"type_id":2,"type":"fulfillment","bitmask":11,"threshold":3,"subfulfillments":[{"type_id":0,"bitmask":3,"hash":"5wbD6GsVBReHetMUw17QcNne8BjB1xSKRoU4JYpafEx5","max_fulfillment_length":5,"type":"condition","weight":1},{"type_id":0,"bitmask":3,"hash":"EuNEkS8TUYaTngMPGiS3DHdApYBf2YYQVdg3hHHTnPDx","max_fulfillment_length":11,"type":"condition","weight":1},{"type_id":0,"bitmask":3,"hash":"Ay3VvUjfEnEhCWxJMGLGBpWTS5iu2nVB64wcsYkPnCqd","max_fulfillment_length":5,"type":"condition","weight":1},{"type_id":0,"bitmask":3,"hash":"H7nD6xkFRm99GzAxvA5JG8DQSZBEGdiUdnYuh7714vMW","max_fulfillment_length":10,"type":"condition","weight":1},{"type_id":0,"bitmask":3,"hash":"8EmZwLhhFAZ9QgHgHfgMokfQ2CfzXaLbyEz4uaXaJyq4","max_fulfillment_length":7,"type":"condition","weight":1},{"type_id":0,"bitmask":3,"hash":"DFf8KSmzgHEarJ2RPJmyDGTvnS8E8MjxkDNVjNsUN8Hr","max_fulfillment_length":8,"type":"condition","weight":1},{"type_id":0,"bitmask":3,"hash":"3qUBtEhzGazLRTM9c3JWKGPTnrkgxbtEoezh7WaJuJBS","max_fulfillment_length":3,"type":"condition","weight":1},{"type_id":0,"bitmask":3,"hash":"4w6YMt6nH3oSsA1uTk6Vmqvqsa9eSquKSAxWtDWPrzTg","max_fulfillment_length":4,"type":"condition","weight":1},{"type_id":0,"bitmask":3,"hash":"HT5nStZQ4x2ecqwZFiKtJWs14TVWiViNVrfFpEqpvf3u","max_fulfillment_length":5,"type":"condition","weight":1},{"type_id":0,"bitmask":3,"hash":"JBMM3eF7iEdJ9XxwSfHe4JrwkcFQExTsiCF4YSGyuJoH","max_fulfillment_length":3,"type":"condition","weight":1}],"weight":1}]},"uri":"cc:2:2b:RnwQdfUJUqPi-zhtS-5WeijFScfyxo2tUVL56T6rQXQ:439"},"public_keys":["79K8SPZbeSDYXBrWgt3dsNmYTZbKNtdYQ5XrjA9XEWfG"]}],"inputs":[{"fulfillment":"cf:4:W0dEBH4MFkphXyUzeuY04q8z2visobk5dtiggDfGdOfdku6Uawyk3SF0B6mWirTC6XC7CaWCKi62xRDXnWXQ_yl-A-Ihi315r65IpGf1AIJhLryNx1rcKocczKUCsAsB","fulfills":null,"owners_before":["79K8SPZbeSDYXBrWgt3dsNmYTZbKNtdYQ5XrjA9XEWfG"]}],"metadata":null,"asset":{"data":{"item":"shirt","frequency":10,"timestamp":"1493634802"}},"version":"0.9"}

Provide ThresholdSha256Fulfillment.add_subfulfillments()?

Being able to pass multiple fulfillments at once would be convenient. E.g., given:

alice_ed25519 = Ed25519Fulfillment(public_key=alice.verifying_key)
bob_ed25519 = Ed25519Fulfillment(public_key=bob.verifying_key)
threshold_sha256 = ThresholdSha256Fulfillment(threshold=2)

currently:

threshold_sha256.add_subfulfillment(alice_ed25519)
threshold_sha256.add_subfulfillment(bob_ed25519)

proposal:

threshold_sha256.add_subfulfillments(alice_ed25519, bob_ed25519)

Why is Condition a metaclass?

On a related note, why not provide an __init__ to Condition?

Such that instead of the following

condition = Condition()
condition.type_id = type_id
condition.bitmask = bitmask
condition.hash = _hash
condition.max_fulfillment_length = max_fulfillment_length

we could simply do:

condition = Condition(
    type_id=self.type_id,
    bitmask=self.bitmask,
    hash=_hash,
    max_fulfillment_length=max_fulfillment_length,
)

GET/UPDATE/DELETE of subcondition

We want to update a single subcondition
hence try to find the path of the subcondition or better ways to navigate subconditions

example

GET/DEL/UPDATE fulfillment.subcondition_by_path([(type_id=cc.types.THRESHOLD, args=[branch_nb]), (type_id=cc.types.ED25519, args=[public_key]))]

the args list

[(type_id=cc.types.THRESHOLD, args=[branch_nb]), (type_id=cc.types.ED25519, args=[public_key])]

is an ordered selector for each depth in the tree so at depth=0 you will look for a THRESHOLD and select subcondition with branch_nb

Where to validate a condition's subtypes?

Some questions:

  • Should the implementation silently ignore extra unsupported subtypes?

If not, then when should the implementation complain about it?

  • At parsing time?
  • When .validate() is explicitly called?

As an example, if we were to validate the subtypes when parsing, we could do so:

class ConditionTypes(BitString):
    namedValues = NamedValues(
        ('preImageSha256', 0),
        ('prefixSha256', 1),
        ('thresholdSha256', 2),
        ('rsaSha256', 3),
        ('ed25519Sha256', 4),
    )
    subtypeSpec = ValueSizeConstraint(0, 5)

The line subtypeSpec = ValueSizeConstraint(0, 5) requires the length of the BIT STRING to be no longer than 5.

PreimageSha256 validation returns only True can be dangerous

See this method: https://github.com/bigchaindb/cryptoconditions/blob/master/cryptoconditions/types/sha256.py#L120

PreimageSha256.validate always yields True, while all other respective types validate by checking external parameters (usually the message parameter).
A user would expect that calling .validate on all present fulfillments in a transaction to (at least partially) validate the transaction.
However, for a PreimageSha256 fulfillment, a comparison between the input condition and the newly created fulfillment's condition will also have to happen. In BigchainDB, this case is handled here:
https://github.com/bigchaindb/bigchaindb/blob/master/bigchaindb/util.py#L458

To avoid pitfalls for users of this library it would be nice if we could force the submission of the input-condition and then yield the respective boolean in the validate method.

Make type match type_id

Currently, the 'type' field only shows either 'condition' or 'fulfillment', whereas the 'type_id' is set according to the rfc.

Example:

>>> Condition.from_uri('cc:2:2b:mJUaGKCuF5n-3tfXM2U81VYtHbX-N8MP6kz8R-ASwNQ:146').to_dict()
{'bitmask': 43,
 'hash': 'BGcqXDoe5DeQB87es8AQEDWr3A6Dvjuq3egZF5sZ1qfy',
 'max_fulfillment_length': 146,
 'type': 'condition',
 'type_id': 2}

This issue proposes to change the above to:

>>> Condition.from_uri('cc:2:2b:mJUaGKCuF5n-3tfXM2U81VYtHbX-N8MP6kz8R-ASwNQ:146').to_dict()
{'bitmask': 43,
 'hash': 'BGcqXDoe5DeQB87es8AQEDWr3A6Dvjuq3egZF5sZ1qfy',
 'max_fulfillment_length': 146,
 'type': 'prefix_sha_256',
 'type_id': 2}

Unless @sbellem's understanding is wrong this would be in line with the RFC:

2.4. Condition

Below are the string and binary encoding formats for a condition.

2.4.1. String Format

Conditions are ASCII encoded as:

"cc:" BASE16(type) ":" BASE16(featureBitmask) ":"
      BASE64URL(fingerprint) ":" BASE10(maxFulfillmentLength)

2.4.2. Binary Format

Conditions are binary encoded as:

  Condition ::= SEQUENCE {
    type ConditionType,
    featureBitmask INTEGER (0..MAX),
    fingerprint OCTET STRING,
    maxFulfillmentLength INTEGER (0..MAX)
  }

```text
  ConditionType ::= INTEGER {
    preimageSha256(0),
    rsaSha256(1),
    prefixSha256(2),
    thresholdSha256(3),
    ed25519(4)
  } (0..65535)

Perhaps a different, issue, but raising here as it related. Why not use the word type to denote the id, since it is what the spec uses? We could use type_name to store the name.

Use namedtuples for registered types

Simply to make it more convenient to deal with registered types.

Example:

RegisteredType = namedtuple('RegisteredType', 'type_id name class_')

registered_type = RegisteredType(type_id=0, name='n', class_='c')

registered_type.name

Remove support for weighted threshold conditions

Assuming we wish to follow the reference implementation (interledger/five-bells-condition). See commit interledgerjs/five-bells-condition@2059af5

Rewriting the commit message here for convenience:

The fact that threshold conditions are weighted doesn't seem to provide enough of a benefit to warrant the complexity this feature adds. We will take out the weights for now and possibly add a weighted threshold condition type in the future.

BREAKING: Threshold condition are no longer weighted.

Could Fulfillment.sign() return the signature?

ed25519_fulfillment.sign(message=msg.encode(), private_key=sk)

returns None

proposal:

def sign(self, message, private_key):
    sk = private_key
    vk = sk.get_verifying_key()
    self.public_key = vk
    self.signature = sk.sign(message, encoding='bytes')
    return self.signature

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.