0

I'm trying to add the first block to the supply chain, because the validator doesn't accept the batch.

[2019-11-05 17:40:31.594 DEBUG    publisher] Batch c14df4b31bd7d52cf033a0eb1436b98be3d9ff6b06affbd73ae55f11a7cc0cc33aa6f160f7712d628e2ac644b4b1804e3156bc8190694cb9c468f4ec70b9eb05 invalid, not added to block.
[2019-11-05 17:40:31.595 DEBUG    publisher] Abandoning block (1, S:, P:eb6af88e): no batches added

I installed Sawtooth and the Supply Chain on Ubuntu 16.04. I'm using the following Python Code to send the transaction. I'm not sure about the payload. I've got this from sample data of the fish client example. Is it perhaps necessary to change the keys?

#Creating a Private Key and Signer
from sawtooth_signing import create_context
from sawtooth_signing import CryptoFactory
from hashlib import sha512

context = create_context('secp256k1')
private_key = context.new_random_private_key()
signer = CryptoFactory(context).new_signer(private_key)
public_key = signer.get_public_key()

#Encoding Your Payload
import cbor

payload = {
      "username": "ahab",
      "password": "ahab",
      "publicKey": public_key.as_hex(),
      "name": "Ahab",
      "email": "ahab@pequod.net",
      "privateKey": "063f9ca21d4ef4955f3e120374f7c22272f42106c466a91d01779efba22c2cb6",
      "encryptedKey": "{\"iv\":\"sKGty1gSvZGmCwzkGy0vvg==\",\"v\":1,\"iter\":10000,\"ks\":128,\"ts\":64,\"mode\":\"ccm\",\"adata\":\"\",\"cipher\":\"aes\",\"salt\":\"lYT7rTJpTV0=\",\"ct\":\"taU8UNB5oJrquzEiXBV+rTTnEq9XmaO9BKeLQQWWuyXJdZ6wR9G+FYrKPkYnXc30iS/9amSG272C8qqnPdM4OE0dvjIdWgSd\"}",
      "hashedPassword": "KNYr+guWkg77DbaWofgK72LrNdaQzzJGIkk2rEHqP9Y="
    }

payload_bytes = cbor.dumps(payload)

#Create the Transaction Header
from hashlib import sha512
from sawtooth_sdk.protobuf.transaction_pb2 import TransactionHeader

txn_header_bytes = TransactionHeader(
    family_name='supply_chain',
    family_version='1.1',
    #inputs=[],
    #outputs=[],
    signer_public_key=signer.get_public_key().as_hex(),
    # In this example, we're signing the batch with the same private key,
    # but the batch can be signed by another party, in which case, the
    # public key will need to be associated with that key.
    batcher_public_key=signer.get_public_key().as_hex(),
    # In this example, there are no dependencies.  This list should include
    # an previous transaction header signatures that must be applied for
    # this transaction to successfully commit.
    # For example,
    # dependencies=['540a6803971d1880ec73a96cb97815a95d374cbad5d865925e5aa0432fcf1931539afe10310c122c5eaae15df61236079abbf4f258889359c4d175516934484a'],
    dependencies=[],
    payload_sha512=sha512(payload_bytes).hexdigest()
).SerializeToString()

#Create the Transaction
from sawtooth_sdk.protobuf.transaction_pb2 import Transaction

signature = signer.sign(txn_header_bytes)

txn = Transaction(
    header=txn_header_bytes,
    header_signature=signature,
    payload= payload_bytes
)

#Create the BatchHeader
from sawtooth_sdk.protobuf.batch_pb2 import BatchHeader

txns = [txn]

batch_header_bytes = BatchHeader(
    signer_public_key=signer.get_public_key().as_hex(),
    transaction_ids=[txn.header_signature for txn in txns],
).SerializeToString()

#Create the Batch
from sawtooth_sdk.protobuf.batch_pb2 import Batch

signature = signer.sign(batch_header_bytes)

batch = Batch(
    header=batch_header_bytes,
    header_signature=signature,
    transactions=txns
)

#Encode the Batch(es) in a BatchList
from sawtooth_sdk.protobuf.batch_pb2 import BatchList

batch_list_bytes = BatchList(batches=[batch]).SerializeToString()

#Submitting Batches to the Validator
import urllib.request
from urllib.error import HTTPError

try:
    request = urllib.request.Request(
        'http://localhost:8008/batches',
        batch_list_bytes,
        method='POST',
        headers={'Content-Type': 'application/octet-stream'})
    response = urllib.request.urlopen(request)


except HTTPError as e:
    response = e.file
Henrik
  • 43
  • 6

2 Answers2

0

Your transaction is missing a nonce. That is required. I do not know what else is missing, if anything.

If the batch is invalid, it is because it's not well-formed (missing parameters or incorrectly set parameters).

You can enable verbose debugging by starting the client, REST API, Validator, and your transaction processor with -vvv added to the command line for all 3. If it is too verbose, just pass -vv.

Dan Anderson
  • 2,265
  • 1
  • 9
  • 20
  • Thanks for your help! But it doesn't work. I think there is something wrong with my private and public keys. Do you have an idea? – Henrik Nov 12 '19 at 07:48
  • You can reinstall Sawtooth as instructed in the `Sawtooth Administration Guide` carefully following instructions on generating your keys. First remove your keys under `/etc/sawtooth/` and `~/.sawtooth/` and the blockchain lmdb files under `/var/lib/sawtooth/` – Dan Anderson Nov 12 '19 at 22:04
0

I found a solution for my case. I used the .proto files of the Supply Chain Repo and I compiled these files to Python files. Then I took the addressing.py and the supply_chain_message_factory.py of the Supply Chain Repo. I changed the imports in supply_chain_message_factory.py and now I can create an agent with main.py.

from sc_message_factory import SupplyChainMessageFactory
import urllib.request
from urllib.error import HTTPError

#Create new agent
new_message = SupplyChainMessageFactory()
transaction = new_message.create_agent('test')
batch = new_message.create_batch(transaction)

try:
    request = urllib.request.Request(
        'http://localhost:8008/batches',
        batch,
        method='POST',
        headers={'Content-Type': 'application/octet-stream'})
    response = urllib.request.urlopen(request)

except HTTPError as e:
    response = e.file
Henrik
  • 43
  • 6