Я пытаюсь настроить пилообразную сеть с несколькими узлами, используя sawtooth 1.2. Я протестировал файл docker compose с контейнерами intkey по умолчанию, и он заработал.
Но когда я попытался настроить intkey с помощью NodeJs SDK и попытался подключиться к валидатору, соединение не отвечало , Также, когда я пытаюсь просмотреть http://localhost: 8008 / пакеты , URL-адрес недоступен.
docker -компонентный файл
version: "2.1"
volumes:
poet-shared:
services:
shell:
image: hyperledger/sawtooth-shell:chime
container_name: sawtooth-shell-default
entrypoint: "bash -c \"\
sawtooth keygen && \
tail -f /dev/null \
\""
validator-0:
image: hyperledger/sawtooth-validator:chime
container_name: sawtooth-validator-default-0
expose:
- 4004
- 5050
- 8800
volumes:
- poet-shared:/poet-shared
command: "bash -c \"\
sawadm keygen --force && \
mkdir -p /poet-shared/validator-0 || true && \
cp -a /etc/sawtooth/keys /poet-shared/validator-0/ && \
while [ ! -f /poet-shared/poet-enclave-measurement ]; do sleep 1; done && \
while [ ! -f /poet-shared/poet-enclave-basename ]; do sleep 1; done && \
while [ ! -f /poet-shared/poet.batch ]; do sleep 1; done && \
cp /poet-shared/poet.batch / && \
sawset genesis \
-k /etc/sawtooth/keys/validator.priv \
-o config-genesis.batch && \
sawset proposal create \
-k /etc/sawtooth/keys/validator.priv \
sawtooth.consensus.algorithm.name=PoET \
sawtooth.consensus.algorithm.version=0.1 \
sawtooth.poet.report_public_key_pem=\
\\\"$$(cat /poet-shared/simulator_rk_pub.pem)\\\" \
sawtooth.poet.valid_enclave_measurements=$$(cat /poet-shared/poet-enclave-measurement) \
sawtooth.poet.valid_enclave_basenames=$$(cat /poet-shared/poet-enclave-basename) \
-o config.batch && \
sawset proposal create \
-k /etc/sawtooth/keys/validator.priv \
sawtooth.poet.target_wait_time=5 \
sawtooth.poet.initial_wait_time=25 \
sawtooth.publisher.max_batches_per_block=100 \
-o poet-settings.batch && \
sawadm genesis \
config-genesis.batch config.batch poet.batch poet-settings.batch && \
sawtooth-validator -v \
--bind network:tcp://eth0:8800 \
--bind component:tcp://eth0:4004 \
--bind consensus:tcp://eth0:5050 \
--peering static \
--endpoint tcp://validator-0:8800 \
--scheduler parallel \
--network-auth trust
\""
environment:
PYTHONPATH: "/project/sawtooth-core/consensus/poet/common:\
/project/sawtooth-core/consensus/poet/simulator:\
/project/sawtooth-core/consensus/poet/core"
stop_signal: SIGKILL
validator-1:
image: hyperledger/sawtooth-validator:chime
container_name: sawtooth-validator-default-1
expose:
- 4004
- 5050
- 8800
volumes:
- poet-shared:/poet-shared
command: |
bash -c "
sawadm keygen --force && \
mkdir -p /poet-shared/validator-1 || true && \
cp -a /etc/sawtooth/keys /poet-shared/validator-1/ && \
sawtooth-validator -v \
--bind network:tcp://eth0:8800 \
--bind component:tcp://eth0:4004 \
--bind consensus:tcp://eth0:5050 \
--peering static \
--endpoint tcp://validator-1:8800 \
--peers tcp://validator-0:8800 \
--scheduler parallel \
--network-auth trust
"
environment:
PYTHONPATH: "/project/sawtooth-core/consensus/poet/common:\
/project/sawtooth-core/consensus/poet/simulator:\
/project/sawtooth-core/consensus/poet/core"
stop_signal: SIGKILL
rest-api-0:
image: hyperledger/sawtooth-rest-api:chime
container_name: sawtooth-rest-api-default-0
expose:
- 8008
command: |
bash -c "
sawtooth-rest-api \
--connect tcp://validator-0:4004 \
--bind rest-api-0:8008
"
stop_signal: SIGKILL
rest-api-1:
image: hyperledger/sawtooth-rest-api:chime
container_name: sawtooth-rest-api-default-1
expose:
- 9008
command: |
bash -c "
sawtooth-rest-api \
--connect tcp://validator-1:4004 \
--bind rest-api-1:9008
"
stop_signal: SIGKILL
settings-tp-0:
image: hyperledger/sawtooth-settings-tp:chime
container_name: sawtooth-settings-tp-default-0
expose:
- 4004
command: settings-tp -v -C tcp://validator-0:4004
stop_signal: SIGKILL
settings-tp-1:
image: hyperledger/sawtooth-settings-tp:chime
container_name: sawtooth-settings-tp-default-1
expose:
- 4004
command: settings-tp -v -C tcp://validator-1:4004
stop_signal: SIGKILL
poet-engine-0:
image: hyperledger/sawtooth-poet-engine:chime
container_name: sawtooth-poet-engine-0
volumes:
- poet-shared:/poet-shared
command: "bash -c \"\
if [ ! -f /poet-shared/poet-enclave-measurement ]; then \
poet enclave measurement >> /poet-shared/poet-enclave-measurement; \
fi && \
if [ ! -f /poet-shared/poet-enclave-basename ]; then \
poet enclave basename >> /poet-shared/poet-enclave-basename; \
fi && \
if [ ! -f /poet-shared/simulator_rk_pub.pem ]; then \
cp /etc/sawtooth/simulator_rk_pub.pem /poet-shared; \
fi && \
while [ ! -f /poet-shared/validator-0/keys/validator.priv ]; do sleep 1; done && \
cp -a /poet-shared/validator-0/keys /etc/sawtooth && \
poet registration create -k /etc/sawtooth/keys/validator.priv -o /poet-shared/poet.batch && \
poet-engine -C tcp://validator-0:5050 --component tcp://validator-0:4004 \
\""
poet-engine-1:
image: hyperledger/sawtooth-poet-engine:chime
container_name: sawtooth-poet-engine-1
volumes:
- poet-shared:/poet-shared
command: "bash -c \"\
while [ ! -f /poet-shared/validator-1/keys/validator.priv ]; do sleep 1; done && \
cp -a /poet-shared/validator-1/keys /etc/sawtooth && \
poet-engine -C tcp://validator-1:5050 --component tcp://validator-1:4004 \
\""
poet-validator-registry-tp-0:
image: hyperledger/sawtooth-poet-validator-registry-tp:chime
container_name: sawtooth-poet-validator-registry-tp-0
expose:
- 4004
command: poet-validator-registry-tp -C tcp://validator-0:4004
environment:
PYTHONPATH: /project/sawtooth-core/consensus/poet/common
stop_signal: SIGKILL
poet-validator-registry-tp-1:
image: hyperledger/sawtooth-poet-validator-registry-tp:chime
container_name: sawtooth-poet-validator-registry-tp-1
expose:
- 4004
command: poet-validator-registry-tp -C tcp://validator-1:4004
environment:
PYTHONPATH: /project/sawtooth-core/consensus/poet/common
stop_signal: SIGKILL
обработчик intkey
/**
* Copyright 2016 Intel Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ------------------------------------------------------------------------------
*/
'use strict'
const { TransactionHandler } = require('sawtooth-sdk/processor/handler')
const {
InvalidTransaction,
InternalError
} = require('sawtooth-sdk/processor/exceptions')
const crypto = require('crypto')
const cbor = require('cbor')
// Constants defined in intkey specification
const MIN_VALUE = 0
const MAX_VALUE = 4294967295
const MAX_NAME_LENGTH = 20
const _hash = (x) =>
crypto.createHash('sha512').update(x).digest('hex').toLowerCase()
const INT_KEY_FAMILY = 'intkey'
const INT_KEY_NAMESPACE = _hash(INT_KEY_FAMILY).substring(0, 6)
const _decodeCbor = (buffer) =>
new Promise((resolve, reject) =>
cbor.decodeFirst(buffer, (err, obj) => (err ? reject(err) : resolve(obj)))
)
const _toInternalError = (err) => {
let message = (err.message) ? err.message : err
throw new InternalError(message)
}
const _setEntry = (context, address, stateValue) => {
let entries = {
[address]: cbor.encode(stateValue)
}
return context.setState(entries)
}
const _applySet = (context, address, name, value) => (possibleAddressValues) => {
let stateValueRep = possibleAddressValues[address]
let stateValue
if (stateValueRep && stateValueRep.length > 0) {
stateValue = cbor.decodeFirstSync(stateValueRep)
let stateName = stateValue[name]
if (stateName) {
throw new InvalidTransaction(
`Verb is "set" but Name already in state, Name: ${name} Value: ${stateName}`
)
}
}
// 'set' passes checks so store it in the state
if (!stateValue) {
stateValue = {}
}
stateValue[name] = value
return _setEntry(context, address, stateValue)
}
const _applyOperator = (verb, op) => (context, address, name, value) => (possibleAddressValues) => {
let stateValueRep = possibleAddressValues[address]
if (!stateValueRep || stateValueRep.length === 0) {
throw new InvalidTransaction(`Verb is ${verb} but Name is not in state`)
}
let stateValue = cbor.decodeFirstSync(stateValueRep)
if (stateValue[name] === null || stateValue[name] === undefined) {
throw new InvalidTransaction(`Verb is ${verb} but Name is not in state`)
}
const result = op(stateValue[name], value)
if (result < MIN_VALUE) {
throw new InvalidTransaction(
`Verb is ${verb}, but result would be less than ${MIN_VALUE}`
)
}
if (result > MAX_VALUE) {
throw new InvalidTransaction(
`Verb is ${verb}, but result would be greater than ${MAX_VALUE}`
)
}
// Increment the value in state by value
// stateValue[name] = op(stateValue[name], value)
stateValue[name] = result
return _setEntry(context, address, stateValue)
}
const _applyInc = _applyOperator('inc', (x, y) => x + y)
const _applyDec = _applyOperator('dec', (x, y) => x - y)
class IntegerKeyHandler extends TransactionHandler {
constructor () {
super(INT_KEY_FAMILY, ['1.0'], [INT_KEY_NAMESPACE])
}
apply (transactionProcessRequest, context) {
return _decodeCbor(transactionProcessRequest.payload)
.catch(_toInternalError)
.then((update) => {
//
// Validate the update
let name = update.Name
if (!name) {
throw new InvalidTransaction('Name is required')
}
if (name.length > MAX_NAME_LENGTH) {
throw new InvalidTransaction(
`Name must be a string of no more than ${MAX_NAME_LENGTH} characters`
)
}
let verb = update.Verb
if (!verb) {
throw new InvalidTransaction('Verb is required')
}
let value = update.Value
if (value === null || value === undefined) {
throw new InvalidTransaction('Value is required')
}
let parsed = parseInt(value)
if (parsed !== value || parsed < MIN_VALUE || parsed > MAX_VALUE) {
throw new InvalidTransaction(
`Value must be an integer ` +
`no less than ${MIN_VALUE} and ` +
`no greater than ${MAX_VALUE}`)
}
value = parsed
// Determine the action to apply based on the verb
let actionFn
if (verb === 'set') {
actionFn = _applySet
} else if (verb === 'dec') {
actionFn = _applyDec
} else if (verb === 'inc') {
actionFn = _applyInc
} else {
throw new InvalidTransaction(`Verb must be set, inc, dec not ${verb}`)
}
let address = INT_KEY_NAMESPACE + _hash(name).slice(-64)
// Get the current state, for the key's address:
let getPromise = context.getState([address])
// Apply the action to the promise's result:
let actionPromise = getPromise.then(
actionFn(context, address, name, value)
)
// Validate that the action promise results in the correctly set address:
return actionPromise.then(addresses => {
if (addresses.length === 0) {
throw new InternalError('State Error!')
}
console.log(`Verb: ${verb} Name: ${name} Value: ${value}`)
})
})
}
}
module.exports = IntegerKeyHandler
индекс intkey
/**
* Copyright 2016 Intel Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ------------------------------------------------------------------------------
*/
'use strict'
const { TransactionProcessor } = require('sawtooth-sdk/processor')
const IntegerKeyHandler = require('./handler')
const address = "tcp://localhost:4004";
const transactionProcessor = new TransactionProcessor(address)
transactionProcessor.addHandler(new IntegerKeyHandler())
transactionProcessor.start()