From a384ed4ed19e186c12b24a1298d293908191b350 Mon Sep 17 00:00:00 2001 From: Andrea Gunderson Date: Mon, 18 Mar 2019 18:46:05 -0500 Subject: [PATCH 1/3] Add initial grid-sdk with track and trace protos This is the start of the grid-sdk that can be used by developers to easily pull in other grid components. Initially, it contains the track and trace protos. Also includes proto traits that will be used to guard the rest of the code from using protobufs directly in the future. Signed-off-by: Andrea Gunderson --- .gitignore | 3 + sdk/Cargo.toml | 28 ++++ sdk/build.rs | 82 +++++++++ sdk/protos/track_and_trace_agent.proto | 32 ++++ sdk/protos/track_and_trace_payload.proto | 137 +++++++++++++++ sdk/protos/track_and_trace_property.proto | 193 ++++++++++++++++++++++ sdk/protos/track_and_trace_proposal.proto | 66 ++++++++ sdk/protos/track_and_trace_record.proto | 59 +++++++ sdk/src/lib.rs | 15 ++ sdk/src/protos.rs | 77 +++++++++ 10 files changed, 692 insertions(+) create mode 100644 sdk/Cargo.toml create mode 100644 sdk/build.rs create mode 100644 sdk/protos/track_and_trace_agent.proto create mode 100644 sdk/protos/track_and_trace_payload.proto create mode 100644 sdk/protos/track_and_trace_property.proto create mode 100644 sdk/protos/track_and_trace_proposal.proto create mode 100644 sdk/protos/track_and_trace_record.proto create mode 100644 sdk/src/lib.rs create mode 100644 sdk/src/protos.rs diff --git a/.gitignore b/.gitignore index 64a3b66337..df5e062b8a 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,9 @@ contracts/track_and_trace/bin/ contracts/track_and_trace/target/ contracts/track_and_trace/src/messages/ +sdk/Cargo.lock +sdk/target + # Node **/node_modules **/package-lock.json diff --git a/sdk/Cargo.toml b/sdk/Cargo.toml new file mode 100644 index 0000000000..5261d81667 --- /dev/null +++ b/sdk/Cargo.toml @@ -0,0 +1,28 @@ +# Copyright 2019 Cargill Incorporated +# +# 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. + +[package] +name = "grid-sdk" +version = "0.1.0" +authors = ["Cargill Incorporated"] +description = "Grid SDK" +homepage = "https://grid.hyperledger.org" +edition = "2018" + +[dependencies] +protobuf = "2" + +[build-dependencies] +protoc-rust = "2" +glob = "0.2" diff --git a/sdk/build.rs b/sdk/build.rs new file mode 100644 index 0000000000..bf601e0e35 --- /dev/null +++ b/sdk/build.rs @@ -0,0 +1,82 @@ +/* + * Copyright 2017 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. + * ------------------------------------------------------------------------------ + */ + +extern crate glob; +extern crate protoc_rust; + +use std::env; +use std::fs; +use std::fs::File; +use std::io::Write; +use std::path::Path; + +use protoc_rust::Customize; + +fn main() { + // Generate protobuf files + let proto_src_files = glob_simple("protos/*.proto"); + println!("{:?}", proto_src_files); + + let out_dir = env::var("OUT_DIR").expect("No OUT_DIR env variable"); + let dest_path = Path::new(&out_dir).join("protos"); + fs::create_dir_all(&dest_path).expect("Unable to create proto destination directory"); + + let mod_file_content = proto_src_files + .iter() + .map(|proto_file| { + let proto_path = Path::new(proto_file); + format!( + "pub mod {};", + proto_path + .file_stem() + .expect("Unable to extract stem") + .to_str() + .expect("Unable to extract filename") + ) + }) + .collect::>() + .join("\n"); + + let mut mod_file = File::create(dest_path.join("mod.rs")).unwrap(); + mod_file + .write_all(mod_file_content.as_bytes()) + .expect("Unable to write mod file"); + + protoc_rust::run(protoc_rust::Args { + out_dir: &dest_path.to_str().expect("Invalid proto destination path"), + input: &proto_src_files + .iter() + .map(|a| a.as_ref()) + .collect::>(), + includes: &["src", "protos"], + customize: Customize::default(), + }) + .expect("unable to run protoc"); +} + +fn glob_simple(pattern: &str) -> Vec { + glob::glob(pattern) + .expect("glob") + .map(|g| { + g.expect("item") + .as_path() + .to_str() + .expect("utf-8") + .to_owned() + }) + .collect() +} diff --git a/sdk/protos/track_and_trace_agent.proto b/sdk/protos/track_and_trace_agent.proto new file mode 100644 index 0000000000..b9713d26f1 --- /dev/null +++ b/sdk/protos/track_and_trace_agent.proto @@ -0,0 +1,32 @@ +// Copyright 2017 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. +// ----------------------------------------------------------------------------- + +syntax = "proto3"; + + +message Agent { + string public_key = 1; + + // A human readable name identifying the Agent + string name = 2; + + // Unix UTC timestamp of approximately when this agent was registered + uint64 timestamp = 3; +} + + +message AgentContainer { + repeated Agent entries = 1; +} diff --git a/sdk/protos/track_and_trace_payload.proto b/sdk/protos/track_and_trace_payload.proto new file mode 100644 index 0000000000..2187221e92 --- /dev/null +++ b/sdk/protos/track_and_trace_payload.proto @@ -0,0 +1,137 @@ +// Copyright 2017 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. +// ----------------------------------------------------------------------------- + +syntax = "proto3"; + +import "track_and_trace_property.proto"; +import "track_and_trace_proposal.proto"; + + +message SCPayload { + enum Action { + CREATE_AGENT = 0; + CREATE_RECORD = 1; + FINALIZE_RECORD = 2; + CREATE_RECORD_TYPE = 3; + UPDATE_PROPERTIES = 4; + CREATE_PROPOSAL = 5; + ANSWER_PROPOSAL = 6; + REVOKE_REPORTER = 7; + } + + Action action = 1; + + // Approximately when transaction was submitted, as a Unix UTC + // timestamp + uint64 timestamp = 2; + + // The transaction handler will read from just one of these fields + // according to the Action. + CreateAgentAction create_agent = 3; + CreateRecordAction create_record = 4; + FinalizeRecordAction finalize_record = 5; + CreateRecordTypeAction create_record_type = 6; + UpdatePropertiesAction update_properties = 7; + CreateProposalAction create_proposal = 8; + AnswerProposalAction answer_proposal = 9; + RevokeReporterAction revoke_reporter = 10; +} + + +message CreateAgentAction { + // The human-readable name of the Agent. This does not need to be + // unique. + string name = 1; +} + + +message CreateRecordAction { + // The natural key of the Record + string record_id = 1; + + // The name of the RecordType this Record belongs to + string record_type = 2; + + repeated PropertyValue properties = 3; +} + + +message FinalizeRecordAction { + // The natural key of the Record + string record_id = 1; +} + + +message CreateRecordTypeAction { + string name = 1; + + repeated PropertySchema properties = 2; +} + + +message UpdatePropertiesAction { + // The natural key of the Record + string record_id = 1; + + repeated PropertyValue properties = 2; +} + + +message CreateProposalAction { + // The natural key of the Record + string record_id = 1; + + // the public key of the Agent to whom the Proposal is sent + // (must be different from the Agent creating the Proposal) + string receiving_agent = 2; + + Proposal.Role role = 3; + + repeated string properties = 4; +} + + +message AnswerProposalAction { + enum Response { + ACCEPT = 0; + REJECT = 1; + CANCEL = 2; + } + + // The natural key of the Record + string record_id = 1; + + // The public key of the Agent to whom the proposal is sent + string receiving_agent = 2; + + // The role being proposed (owner, custodian, or reporter) + Proposal.Role role = 3; + + // The respose to the Proposal (accept, reject, or cancel) + Response response = 4; +} + + +message RevokeReporterAction { + // The natural key of the Record + string record_id = 1; + + // The reporter's public key + string reporter_id = 2; + + // The names of the Properties for which the reporter's + // authorization is revoked + repeated string properties = 3; +} diff --git a/sdk/protos/track_and_trace_property.proto b/sdk/protos/track_and_trace_property.proto new file mode 100644 index 0000000000..13c7ecad69 --- /dev/null +++ b/sdk/protos/track_and_trace_property.proto @@ -0,0 +1,193 @@ +// Copyright 2017 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. +// ----------------------------------------------------------------------------- + +syntax = "proto3"; + + +message Property { + message Reporter { + // The public key of the Agent authorized to report updates. + string public_key = 1; + bool authorized = 2; + // An update must be stored with some way of identifying which + // Agent sent it. Storing a full public key for each update would + // be wasteful, so instead Reporters are identified by their index + // in the `reporters` field. + uint32 index = 3; + } + + // The name of the Property, e.g. "temperature". This must be unique + // among Properties. + string name = 1; + + // The natural key of the Property's associated Record. + string record_id = 2; + + // The Property's type (int, string, etc.) + PropertySchema.DataType data_type = 3; + + // The Reporters authorized to send updates, sorted by index. New + // Reporters should be given an index equal to the number of + // Reporters already authorized. + repeated Reporter reporters = 4; + + // The page to which new updates are added. This number represents + // the last 4 hex characters of the page's address. Consequently, + // it should not exceed 16^4 = 65536. + uint32 current_page = 5; + + // A flag indicating whether the first 16^4 pages have been filled. + // This is used to calculate the last four hex characters of the + // address of the page containing the earliest updates. When it is + // false, the earliest page's address will end in "0001". When it is + // true, the earliest page's address will be one more than the + // current_page, or "0001" if the current_page is "ffff". + bool wrapped = 6; + + // If set to true, values may only be set for this Property + // during Record creation, not later with updates. + bool fixed = 9; + + // Used with numbers to communicate how the integer value should be converted + // to a fractional number. Uses the same principle as scientific notation. + // A number value of 1, with an exponent of 3, would be 1,000 (1 * 10^3). + // A number value of 1, with an exponent of -3, would be 0.001 (1 * 10^-3). + sint32 number_exponent = 10; + + // Used with ENUM data types, the string names of available options + repeated string enum_options = 11; + + // Used with STRUCT data types, defines the properties a struct must contain + repeated PropertySchema struct_properties = 12; + + // This optional metadata describes the unit a Property is measured in + string unit = 20; +} + + +message PropertyContainer { + repeated Property entries = 1; +} + + +message PropertySchema { + enum DataType { + TYPE_UNSET = 0; + BYTES = 1; + BOOLEAN = 2; + NUMBER = 3; + STRING = 4; + ENUM = 5; + STRUCT = 6; + LOCATION = 7; + } + + // The name of the property, e.g. "temperature" + string name = 1; + + // The Property's type (int, string, etc.) + DataType data_type = 2; + + // A flag indicating whether initial values must be provided for the + // Property when a Record is created. + bool required = 3; + + // Another flag. If set to true, values may only be set for this Property + // during Record creation, not later with updates. + bool fixed = 4; + + // A flag that indicates a property may not be set at record creation, + // only later during subsequent property updates. + bool delayed = 5; + + // Used with numbers to communicate how the integer value should be converted + // to a fractional number. Uses the same principle as scientific notation. + // A number value of 1, with an exponent of 3, would be 1,000 (1 * 10^3). + // A number value of 1, with an exponent of -3, would be 0.001 (1 * 10^-3). + sint32 number_exponent = 10; + + // Used with ENUM data types, the string names of available options + repeated string enum_options = 11; + + // Used with STRUCT data types, defines the properties a struct must contain + repeated PropertySchema struct_properties = 12; + + // This optional metadata describes the unit a Property is measured in + string unit = 20; +} + + +message PropertyValue { + // The name of the property being set + string name = 1; + + // The PropertyValue's type (int, string, etc.) + PropertySchema.DataType data_type = 2; + + // The type-specific value to initialize or update a Property. Only + // one of these fields should be used, and it should match the type + // specified for this Property in the RecordType. + bytes bytes_value = 11; + bool boolean_value = 12; + sint64 number_value = 13; + string string_value = 14; + string enum_value = 15; + repeated PropertyValue struct_values = 16; + Location location_value = 17; +} + + +message PropertyPage { + message ReportedValue { + // The index of the reporter id in reporters field + uint32 reporter_index = 1; + // Approximately when this value was reported, as a Unix UTC + // timestamp + uint64 timestamp = 2; + + // The type-specific value of the update. Only one of these + // fields should be used, and it should match the type + // specified for this Property in the RecordType. + bytes bytes_value = 11; + bool boolean_value = 12; + sint64 number_value = 13; + string string_value = 14; + uint32 enum_value = 15; + repeated PropertyValue struct_values = 16; + Location location_value = 17; + } + + // The name of the page's associated Property and the record_id of + // its associated Record. These are required to distinguish pages + // with colliding addresses. + string name = 1; + string record_id = 2; + + // ReportedValues are sorted first by timestamp, then by + // reporter_index + repeated ReportedValue reported_values = 3; +} + + +message PropertyPageContainer { + repeated PropertyPage entries = 1; +} + + +message Location { + // Coordinates are expected to be in millionths of a degree + sint64 latitude = 1; + sint64 longitude = 2; +} diff --git a/sdk/protos/track_and_trace_proposal.proto b/sdk/protos/track_and_trace_proposal.proto new file mode 100644 index 0000000000..59d909031b --- /dev/null +++ b/sdk/protos/track_and_trace_proposal.proto @@ -0,0 +1,66 @@ +// Copyright 2017 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. +// ----------------------------------------------------------------------------- + +syntax = "proto3"; + + +message Proposal { + enum Role { + OWNER = 0; + CUSTODIAN = 1; + REPORTER = 2; + } + + enum Status { + OPEN = 0; + ACCEPTED = 1; + REJECTED = 2; + CANCELED = 3; + } + + string record_id = 1; + + // The time at which the Proposal was created + uint64 timestamp = 2; + + // The public key of the Agent sending the Proposal. This Agent must + // be the owner of the Record (or the custodian, if the Proposal is + // to transfer custodianship). + string issuing_agent = 3; + + // The public key of the Agent to whom the Proposal is sent. + string receiving_agent = 4; + + // What the Proposal is for -- transferring ownership, transferring + // custodianship, or authorizing a reporter. + Role role = 5; + + // The names of properties for which the reporter is being authorized + // (empty for owner or custodian transfers) + repeated string properties = 6; + + // The status of the Proposal. For a given Record and receiving + // Agent, there can be only one open Proposal at a time for each + // role. + Status status = 7; + + // The human-readable terms of transfer. + string terms = 8; +} + + +message ProposalContainer { + repeated Proposal entries = 1; +} diff --git a/sdk/protos/track_and_trace_record.proto b/sdk/protos/track_and_trace_record.proto new file mode 100644 index 0000000000..c36eab0448 --- /dev/null +++ b/sdk/protos/track_and_trace_record.proto @@ -0,0 +1,59 @@ +// Copyright 2017 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. +// ----------------------------------------------------------------------------- + +syntax = "proto3"; + +import "track_and_trace_property.proto"; + + +message Record { + message AssociatedAgent { + string agent_id = 1; + uint64 timestamp = 2; + } + + // The user-defined natural key which identifies the object in the + // real world (for example a serial number) + string record_id = 1; + + string record_type = 2; + + // Ordered oldest to newest by timestamp + repeated AssociatedAgent owners = 3; + repeated AssociatedAgent custodians = 4; + + // Flag indicating whether the Record can be updated. If it is set + // to true, then the record has been finalized and no further + // changes can be made to it or its Properties. + bool final = 5; +} + + +message RecordContainer { + repeated Record entries = 1; +} + + +message RecordType { + // A unique human-readable designation for the RecordType + string name = 1; + + repeated PropertySchema properties = 2; +} + + +message RecordTypeContainer { + repeated RecordType entries = 1; +} diff --git a/sdk/src/lib.rs b/sdk/src/lib.rs new file mode 100644 index 0000000000..1a762592b4 --- /dev/null +++ b/sdk/src/lib.rs @@ -0,0 +1,15 @@ +// Copyright 2019 Cargill Incorporated +// +// 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. + +pub mod protos; diff --git a/sdk/src/protos.rs b/sdk/src/protos.rs new file mode 100644 index 0000000000..31a00dcad1 --- /dev/null +++ b/sdk/src/protos.rs @@ -0,0 +1,77 @@ +// Copyright 2018 Bitwise IO, Inc. +// +// 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 std::error::Error as StdError; + +#[derive(Debug)] +pub enum ProtoConversionError { + SerializationError(String), + InvalidTypeError(String), +} + +impl StdError for ProtoConversionError { + fn description(&self) -> &str { + match *self { + ProtoConversionError::SerializationError(ref msg) => msg, + ProtoConversionError::InvalidTypeError(ref msg) => msg, + } + } + + fn cause(&self) -> Option<&StdError> { + match *self { + ProtoConversionError::SerializationError(_) => None, + ProtoConversionError::InvalidTypeError(_) => None, + } + } +} + +impl std::fmt::Display for ProtoConversionError { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + match *self { + ProtoConversionError::SerializationError(ref s) => { + write!(f, "SerializationError: {}", s) + } + ProtoConversionError::InvalidTypeError(ref s) => write!(f, "InvalidTypeError: {}", s), + } + } +} + +pub trait FromProto

: Sized { + fn from_proto(other: P) -> Result; +} + +pub trait FromNative: Sized { + fn from_native(other: N) -> Result; +} + +pub trait IntoNative: Sized +where + T: FromProto, +{ + fn into_native(self) -> Result { + FromProto::from_proto(self) + } +} + +pub trait IntoProto: Sized +where + T: FromNative, +{ + fn into_proto(self) -> Result { + FromNative::from_native(self) + } +} + +// Includes the autogenerated protobuf messages +include!(concat!(env!("OUT_DIR"), "/protos/mod.rs")); From 99721bf445aae6fcf6745d0cd80b58be58861bf0 Mon Sep 17 00:00:00 2001 From: Andrea Gunderson Date: Mon, 18 Mar 2019 18:51:19 -0500 Subject: [PATCH 2/3] Update grid-track-and-trace to use the grid sdk Also fixes some rustfmt issues Signed-off-by: Andrea Gunderson --- contracts/track_and_trace/Cargo.toml | 7 +- contracts/track_and_trace/Dockerfile | 7 +- contracts/track_and_trace/build.rs | 63 ---- contracts/track_and_trace/src/handler.rs | 443 ++++++++++++----------- contracts/track_and_trace/src/main.rs | 8 +- docker-compose.yaml | 4 +- protos/agent.proto | 32 -- protos/payload.proto | 137 ------- protos/property.proto | 193 ---------- protos/proposal.proto | 66 ---- protos/record.proto | 59 --- 11 files changed, 244 insertions(+), 775 deletions(-) delete mode 100644 contracts/track_and_trace/build.rs delete mode 100644 protos/agent.proto delete mode 100644 protos/payload.proto delete mode 100644 protos/property.proto delete mode 100644 protos/proposal.proto delete mode 100644 protos/record.proto diff --git a/contracts/track_and_trace/Cargo.toml b/contracts/track_and_trace/Cargo.toml index 2631ed63e6..d4f7d3f97e 100644 --- a/contracts/track_and_trace/Cargo.toml +++ b/contracts/track_and_trace/Cargo.toml @@ -25,10 +25,7 @@ rust-crypto = "0.2.36" rustc-serialize = "0.3.22" sawtooth-zmq = "0.8.2-dev5" clap = "2" -protobuf = "2" +grid-sdk = { path = "../../sdk" } log = "0.3.0" log4rs = "0.7.0" - -[build-dependencies] -protoc-rust = "2" -glob = "0.2" +protobuf = "2" diff --git a/contracts/track_and_trace/Dockerfile b/contracts/track_and_trace/Dockerfile index 4c3a2d6098..8bf934fff2 100644 --- a/contracts/track_and_trace/Dockerfile +++ b/contracts/track_and_trace/Dockerfile @@ -52,9 +52,14 @@ RUN apt-get update && apt-get install -y protobuf-compiler # - /grid/contracts/track_and_trace/src/messages/ WORKDIR /grid RUN USER=root cargo new --bin contracts/track_and_trace +RUN USER=root cargo new --lib sdk --name grid-sdk + +# copy grid-sdk to build track and trace +WORKDIR /grid/sdk +COPY sdk ./ WORKDIR /grid/contracts/track_and_trace -COPY Cargo.toml Cargo.lock* ./ +COPY contracts/track_and_trace/Cargo.toml contracts/track_and_trace/Cargo.lock* ./ RUN cargo build ENV PATH=$PATH:/grid/contracts/track_and_trace/target/debug/ diff --git a/contracts/track_and_trace/build.rs b/contracts/track_and_trace/build.rs deleted file mode 100644 index 4014992e83..0000000000 --- a/contracts/track_and_trace/build.rs +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright 2017 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. - * ------------------------------------------------------------------------------ - */ - -extern crate glob; -extern crate protoc_rust; - -use std::fs; -use std::io::Write; -use protoc_rust::Customize; - -fn main() { - // Generate protobuf files - let proto_src_files = glob_simple("../../protos/*.proto"); - println!("{:?}", proto_src_files); - - fs::create_dir_all("src/messages").unwrap(); - - protoc_rust::run(protoc_rust::Args { - out_dir: "src/messages", - input: &proto_src_files - .iter() - .map(|a| a.as_ref()) - .collect::>(), - includes: &["src", "../../protos"], - customize: Customize::default(), - }).expect("unable to run protoc"); - - let mut file = fs::File::create("src/messages/mod.rs").unwrap(); - for filename in proto_src_files.iter() { - file.write_all(path_to_mod(&filename).as_bytes()).unwrap(); - } -} - -fn path_to_mod(filename: &String) -> String { - filename.replace("../../protos/", "pub mod ").replace(".proto", ";\n") -} - -fn glob_simple(pattern: &str) -> Vec { - glob::glob(pattern) - .expect("glob") - .map(|g| { - g.expect("item") - .as_path() - .to_str() - .expect("utf-8") - .to_owned() - }) - .collect() -} diff --git a/contracts/track_and_trace/src/handler.rs b/contracts/track_and_trace/src/handler.rs index 47941e6de6..dae7cabd48 100644 --- a/contracts/track_and_trace/src/handler.rs +++ b/contracts/track_and_trace/src/handler.rs @@ -18,26 +18,42 @@ use protobuf::RepeatedField; use std::collections::HashMap; +use grid_sdk::protos::track_and_trace_agent::{Agent, AgentContainer}; +use grid_sdk::protos::track_and_trace_payload::{ + AnswerProposalAction, AnswerProposalAction_Response, CreateAgentAction, + CreateProposalAction, CreateRecordAction, CreateRecordTypeAction, FinalizeRecordAction, + RevokeReporterAction, SCPayload, UpdatePropertiesAction, SCPayload_Action +}; +use grid_sdk::protos::track_and_trace_property::{ + Property, PropertyContainer, PropertyPage, PropertyPageContainer, + PropertyPage_ReportedValue, PropertySchema, PropertySchema_DataType, PropertyValue, + Property_Reporter, +}; +use grid_sdk::protos::track_and_trace_proposal::{ + Proposal, ProposalContainer, Proposal_Role, Proposal_Status, +}; +use grid_sdk::protos::track_and_trace_record::{ + Record, RecordContainer, RecordType, RecordTypeContainer, Record_AssociatedAgent, +}; +use sawtooth_sdk::messages::processor::TpProcessRequest; use sawtooth_sdk::processor::handler::ApplyError; use sawtooth_sdk::processor::handler::TransactionContext; use sawtooth_sdk::processor::handler::TransactionHandler; -use sawtooth_sdk::messages::processor::TpProcessRequest; -use messages::*; use addressing::*; const PROPERTY_PAGE_MAX_LENGTH: usize = 256; #[derive(Debug, Clone)] enum Action { - CreateAgent(payload::CreateAgentAction), - CreateRecord(payload::CreateRecordAction), - FinalizeRecord(payload::FinalizeRecordAction), - CreateRecordType(payload::CreateRecordTypeAction), - UpdateProperties(payload::UpdatePropertiesAction), - CreateProposal(payload::CreateProposalAction), - AnswerProposal(payload::AnswerProposalAction), - RevokeReporter(payload::RevokeReporterAction), + CreateAgent(CreateAgentAction), + CreateRecord(CreateRecordAction), + FinalizeRecord(FinalizeRecordAction), + CreateRecordType(CreateRecordTypeAction), + UpdateProperties(UpdatePropertiesAction), + CreateProposal(CreateProposalAction), + AnswerProposal(AnswerProposalAction), + RevokeReporter(RevokeReporterAction), } struct SupplyChainPayload { @@ -47,18 +63,18 @@ struct SupplyChainPayload { impl SupplyChainPayload { pub fn new(payload: &[u8]) -> Result, ApplyError> { - let payload: payload::SCPayload = match protobuf::parse_from_bytes(payload) { + let payload: SCPayload = match protobuf::parse_from_bytes(payload) { Ok(payload) => payload, Err(_) => { return Err(ApplyError::InvalidTransaction(String::from( "Cannot deserialize payload", - ))) + ))); } }; let supply_chain_action = payload.get_action(); let action = match supply_chain_action { - payload::SCPayload_Action::CREATE_AGENT => { + SCPayload_Action::CREATE_AGENT => { let create_agent = payload.get_create_agent(); if create_agent.get_name() == "" { return Err(ApplyError::InvalidTransaction(String::from( @@ -67,7 +83,7 @@ impl SupplyChainPayload { } Action::CreateAgent(create_agent.clone()) } - payload::SCPayload_Action::CREATE_RECORD => { + SCPayload_Action::CREATE_RECORD => { let create_record = payload.get_create_record(); if create_record.get_record_id() == "" { return Err(ApplyError::InvalidTransaction(String::from( @@ -76,10 +92,10 @@ impl SupplyChainPayload { } Action::CreateRecord(create_record.clone()) } - payload::SCPayload_Action::FINALIZE_RECORD => { + SCPayload_Action::FINALIZE_RECORD => { Action::FinalizeRecord(payload.get_finalize_record().clone()) } - payload::SCPayload_Action::CREATE_RECORD_TYPE => { + SCPayload_Action::CREATE_RECORD_TYPE => { let create_record_type = payload.get_create_record_type(); if create_record_type.get_name() == "" { return Err(ApplyError::InvalidTransaction(String::from( @@ -102,16 +118,16 @@ impl SupplyChainPayload { Action::CreateRecordType(create_record_type.clone()) } - payload::SCPayload_Action::UPDATE_PROPERTIES => { + SCPayload_Action::UPDATE_PROPERTIES => { Action::UpdateProperties(payload.get_update_properties().clone()) } - payload::SCPayload_Action::CREATE_PROPOSAL => { + SCPayload_Action::CREATE_PROPOSAL => { Action::CreateProposal(payload.get_create_proposal().clone()) } - payload::SCPayload_Action::ANSWER_PROPOSAL => { + SCPayload_Action::ANSWER_PROPOSAL => { Action::AnswerProposal(payload.get_answer_proposal().clone()) } - payload::SCPayload_Action::REVOKE_REPORTER => { + SCPayload_Action::REVOKE_REPORTER => { Action::RevokeReporter(payload.get_revoke_reporter().clone()) } }; @@ -119,7 +135,7 @@ impl SupplyChainPayload { 0 => { return Err(ApplyError::InvalidTransaction(String::from( "Timestamp is not set", - ))) + ))); } x => x, }; @@ -148,20 +164,19 @@ impl<'a> SupplyChainState<'a> { SupplyChainState { context: context } } - pub fn get_record(&mut self, record_id: &str) -> Result, ApplyError> { + pub fn get_record(&mut self, record_id: &str) -> Result, ApplyError> { let address = make_record_address(record_id); let d = self.context.get_state(vec![address])?; match d { Some(packed) => { - let records: record::RecordContainer = - match protobuf::parse_from_bytes(packed.as_slice()) { - Ok(records) => records, - Err(_) => { - return Err(ApplyError::InternalError(String::from( - "Cannot deserialize record container", - ))) - } - }; + let records: RecordContainer = match protobuf::parse_from_bytes(packed.as_slice()) { + Ok(records) => records, + Err(_) => { + return Err(ApplyError::InternalError(String::from( + "Cannot deserialize record container", + ))); + } + }; for record in records.get_entries() { if record.record_id == record_id { @@ -174,11 +189,7 @@ impl<'a> SupplyChainState<'a> { } } - pub fn set_record( - &mut self, - record_id: &str, - record: record::Record, - ) -> Result<(), ApplyError> { + pub fn set_record(&mut self, record_id: &str, record: Record) -> Result<(), ApplyError> { let address = make_record_address(record_id); let d = self.context.get_state(vec![address.clone()])?; let mut record_container = match d { @@ -187,10 +198,10 @@ impl<'a> SupplyChainState<'a> { Err(_) => { return Err(ApplyError::InternalError(String::from( "Cannot deserialize record container", - ))) + ))); } }, - None => record::RecordContainer::new(), + None => RecordContainer::new(), }; // remove old record if it exists and sort the records by record id let records = record_container.get_entries().to_vec(); @@ -219,7 +230,7 @@ impl<'a> SupplyChainState<'a> { Err(_) => { return Err(ApplyError::InternalError(String::from( "Cannot serialize record container", - ))) + ))); } }; let mut sets = HashMap::new(); @@ -230,21 +241,18 @@ impl<'a> SupplyChainState<'a> { Ok(()) } - pub fn get_record_type( - &mut self, - type_name: &str, - ) -> Result, ApplyError> { + pub fn get_record_type(&mut self, type_name: &str) -> Result, ApplyError> { let address = make_record_type_address(type_name); let d = self.context.get_state(vec![address])?; match d { Some(packed) => { - let record_types: record::RecordTypeContainer = + let record_types: RecordTypeContainer = match protobuf::parse_from_bytes(packed.as_slice()) { Ok(record_types) => record_types, Err(_) => { return Err(ApplyError::InternalError(String::from( "Cannot deserialize record type container", - ))) + ))); } }; @@ -262,7 +270,7 @@ impl<'a> SupplyChainState<'a> { pub fn set_record_type( &mut self, type_name: &str, - record_type: record::RecordType, + record_type: RecordType, ) -> Result<(), ApplyError> { let address = make_record_type_address(type_name); let d = self.context.get_state(vec![address.clone()])?; @@ -272,10 +280,10 @@ impl<'a> SupplyChainState<'a> { Err(_) => { return Err(ApplyError::InternalError(String::from( "Cannot deserialize record container", - ))) + ))); } }, - None => record::RecordTypeContainer::new(), + None => RecordTypeContainer::new(), }; record_types.entries.push(record_type); @@ -285,7 +293,7 @@ impl<'a> SupplyChainState<'a> { Err(_) => { return Err(ApplyError::InternalError(String::from( "Cannot serialize record type container", - ))) + ))); } }; let mut sets = HashMap::new(); @@ -296,18 +304,18 @@ impl<'a> SupplyChainState<'a> { Ok(()) } - pub fn get_agent(&mut self, agent_id: &str) -> Result, ApplyError> { + pub fn get_agent(&mut self, agent_id: &str) -> Result, ApplyError> { let address = make_agent_address(agent_id); let d = self.context.get_state(vec![address])?; match d { Some(packed) => { - let agents: agent::AgentContainer = + let agents: AgentContainer = match protobuf::parse_from_bytes(packed.as_slice()) { Ok(agents) => agents, Err(_) => { return Err(ApplyError::InternalError(String::from( "Cannot deserialize agent container", - ))) + ))); } }; @@ -322,7 +330,7 @@ impl<'a> SupplyChainState<'a> { } } - pub fn set_agent(&mut self, agent_id: &str, agent: agent::Agent) -> Result<(), ApplyError> { + pub fn set_agent(&mut self, agent_id: &str, agent: Agent) -> Result<(), ApplyError> { let address = make_agent_address(agent_id); let d = self.context.get_state(vec![address.clone()])?; let mut agents = match d { @@ -331,10 +339,10 @@ impl<'a> SupplyChainState<'a> { Err(_) => { return Err(ApplyError::InternalError(String::from( "Cannot deserialize agent container", - ))) + ))); } }, - None => agent::AgentContainer::new(), + None => AgentContainer::new(), }; agents.entries.push(agent); @@ -344,7 +352,7 @@ impl<'a> SupplyChainState<'a> { Err(_) => { return Err(ApplyError::InternalError(String::from( "Cannot serialize agent container", - ))) + ))); } }; let mut sets = HashMap::new(); @@ -359,18 +367,18 @@ impl<'a> SupplyChainState<'a> { &mut self, record_id: &str, property_name: &str, - ) -> Result, ApplyError> { + ) -> Result, ApplyError> { let address = make_property_address(record_id, property_name, 0); let d = self.context.get_state(vec![address])?; match d { Some(packed) => { - let properties: property::PropertyContainer = + let properties: PropertyContainer = match protobuf::parse_from_bytes(packed.as_slice()) { Ok(properties) => properties, Err(_) => { return Err(ApplyError::InternalError(String::from( "Cannot deserialize property container", - ))) + ))); } }; @@ -389,7 +397,7 @@ impl<'a> SupplyChainState<'a> { &mut self, record_id: &str, property_name: &str, - property: property::Property, + property: Property, ) -> Result<(), ApplyError> { let address = make_property_address(record_id, property_name, 0); let d = self.context.get_state(vec![address.clone()])?; @@ -399,10 +407,10 @@ impl<'a> SupplyChainState<'a> { Err(_) => { return Err(ApplyError::InternalError(String::from( "Cannot deserialize property container", - ))) + ))); } }, - None => property::PropertyContainer::new(), + None => PropertyContainer::new(), }; // remove old property if it exists and sort the properties by name let properties = property_container.get_entries().to_vec(); @@ -429,7 +437,7 @@ impl<'a> SupplyChainState<'a> { Err(_) => { return Err(ApplyError::InternalError(String::from( "Cannot serialize property container", - ))) + ))); } }; let mut sets = HashMap::new(); @@ -445,18 +453,18 @@ impl<'a> SupplyChainState<'a> { record_id: &str, property_name: &str, page: u32, - ) -> Result, ApplyError> { + ) -> Result, ApplyError> { let address = make_property_address(record_id, property_name, page); let d = self.context.get_state(vec![address])?; match d { Some(packed) => { - let property_pages: property::PropertyPageContainer = + let property_pages: PropertyPageContainer = match protobuf::parse_from_bytes(packed.as_slice()) { Ok(property_pages) => property_pages, Err(_) => { return Err(ApplyError::InternalError(String::from( "Cannot deserialize property page container", - ))) + ))); } }; @@ -476,7 +484,7 @@ impl<'a> SupplyChainState<'a> { record_id: &str, property_name: &str, page_num: u32, - property_page: property::PropertyPage, + property_page: PropertyPage, ) -> Result<(), ApplyError> { let address = make_property_address(record_id, property_name, page_num); let d = self.context.get_state(vec![address.clone()])?; @@ -486,10 +494,10 @@ impl<'a> SupplyChainState<'a> { Err(_) => { return Err(ApplyError::InternalError(String::from( "Cannot deserialize property page container", - ))) + ))); } }, - None => property::PropertyPageContainer::new(), + None => PropertyPageContainer::new(), }; // remove old property page if it exists and sort the property pages by name let pages = property_pages.get_entries().to_vec(); @@ -516,7 +524,7 @@ impl<'a> SupplyChainState<'a> { Err(_) => { return Err(ApplyError::InternalError(String::from( "Cannot serialize property page container", - ))) + ))); } }; let mut sets = HashMap::new(); @@ -531,18 +539,18 @@ impl<'a> SupplyChainState<'a> { &mut self, record_id: &str, agent_id: &str, - ) -> Result, ApplyError> { + ) -> Result, ApplyError> { let address = make_proposal_address(record_id, agent_id); let d = self.context.get_state(vec![address])?; match d { Some(packed) => { - let proposals: proposal::ProposalContainer = + let proposals: ProposalContainer = match protobuf::parse_from_bytes(packed.as_slice()) { Ok(property_pages) => property_pages, Err(_) => { return Err(ApplyError::InternalError(String::from( "Cannot deserialize proposal container", - ))) + ))); } }; @@ -556,7 +564,7 @@ impl<'a> SupplyChainState<'a> { &mut self, record_id: &str, agent_id: &str, - proposals: proposal::ProposalContainer, + proposals: ProposalContainer, ) -> Result<(), ApplyError> { let address = make_proposal_address(record_id, agent_id); let serialized = match proposals.write_to_bytes() { @@ -564,7 +572,7 @@ impl<'a> SupplyChainState<'a> { Err(_) => { return Err(ApplyError::InternalError(String::from( "Cannot serialize proposal container", - ))) + ))); } }; let mut sets = HashMap::new(); @@ -593,7 +601,7 @@ impl SupplyChainTransactionHandler { fn _create_agent( &self, - payload: payload::CreateAgentAction, + payload: CreateAgentAction, mut state: SupplyChainState, signer: &str, timestamp: u64, @@ -604,13 +612,13 @@ impl SupplyChainTransactionHandler { return Err(ApplyError::InvalidTransaction(format!( "Agent already exists: {}", name - ))) + ))); } Ok(None) => (), Err(err) => return Err(err), } - let mut new_agent = agent::Agent::new(); + let mut new_agent = Agent::new(); new_agent.set_public_key(signer.to_string()); new_agent.set_name(name.to_string()); new_agent.set_timestamp(timestamp); @@ -621,7 +629,7 @@ impl SupplyChainTransactionHandler { fn _create_record( &self, - payload: payload::CreateRecordAction, + payload: CreateRecordAction, mut state: SupplyChainState, signer: &str, timestamp: u64, @@ -632,7 +640,7 @@ impl SupplyChainTransactionHandler { return Err(ApplyError::InvalidTransaction(format!( "Agent is not register: {}", signer - ))) + ))); } Err(err) => return Err(err), } @@ -642,7 +650,7 @@ impl SupplyChainTransactionHandler { return Err(ApplyError::InvalidTransaction(format!( "Record already exists: {}", record_id - ))) + ))); } Ok(None) => (), Err(err) => return Err(err), @@ -655,14 +663,14 @@ impl SupplyChainTransactionHandler { return Err(ApplyError::InvalidTransaction(format!( "Record Type does not exist {}", type_name - ))) + ))); } Err(err) => return Err(err), }; - let mut type_schemata: HashMap<&str, property::PropertySchema> = HashMap::new(); - let mut required_properties: HashMap<&str, property::PropertySchema> = HashMap::new(); - let mut provided_properties: HashMap<&str, property::PropertyValue> = HashMap::new(); + let mut type_schemata: HashMap<&str, PropertySchema> = HashMap::new(); + let mut required_properties: HashMap<&str, PropertySchema> = HashMap::new(); + let mut provided_properties: HashMap<&str, PropertyValue> = HashMap::new(); for property in record_type.get_properties() { type_schemata.insert(property.get_name(), property.clone()); if property.get_required() { @@ -690,7 +698,7 @@ impl SupplyChainTransactionHandler { return Err(ApplyError::InvalidTransaction(format!( "Provided property {} is not in schemata", provided_name - ))) + ))); } }; let provided_type = provided_properties.data_type; @@ -712,12 +720,12 @@ impl SupplyChainTransactionHandler { ))); }; } - let mut new_record = record::Record::new(); + let mut new_record = Record::new(); new_record.set_record_id(record_id.to_string()); new_record.set_record_type(type_name.to_string()); new_record.set_field_final(false); - let mut owner = record::Record_AssociatedAgent::new(); + let mut owner = Record_AssociatedAgent::new(); owner.set_agent_id(signer.to_string()); owner.set_timestamp(timestamp); new_record.owners.push(owner.clone()); @@ -725,13 +733,13 @@ impl SupplyChainTransactionHandler { state.set_record(record_id, new_record)?; - let mut reporter = property::Property_Reporter::new(); + let mut reporter = Property_Reporter::new(); reporter.set_public_key(signer.to_string()); reporter.set_authorized(true); reporter.set_index(0); for (property_name, property) in type_schemata { - let mut new_property = property::Property::new(); + let mut new_property = Property::new(); new_property.set_name(property_name.to_string()); new_property.set_record_id(record_id.to_string()); new_property.set_data_type(property.get_data_type()); @@ -740,15 +748,17 @@ impl SupplyChainTransactionHandler { new_property.set_wrapped(false); new_property.set_fixed(property.get_fixed()); new_property.set_number_exponent(property.get_number_exponent()); - new_property.set_enum_options( - RepeatedField::from_vec(property.get_enum_options().to_vec())); - new_property.set_struct_properties( - RepeatedField::from_vec(property.get_struct_properties().to_vec())); + new_property.set_enum_options(RepeatedField::from_vec( + property.get_enum_options().to_vec(), + )); + new_property.set_struct_properties(RepeatedField::from_vec( + property.get_struct_properties().to_vec(), + )); new_property.set_unit(property.get_unit().to_string()); state.set_property(record_id, property_name, new_property.clone())?; - let mut new_property_page = property::PropertyPage::new(); + let mut new_property_page = PropertyPage::new(); new_property_page.set_name(property_name.to_string()); new_property_page.set_record_id(record_id.to_string()); @@ -774,7 +784,7 @@ impl SupplyChainTransactionHandler { fn _finalize_record( &self, - payload: payload::FinalizeRecordAction, + payload: FinalizeRecordAction, mut state: SupplyChainState, signer: &str, ) -> Result<(), ApplyError> { @@ -785,7 +795,7 @@ impl SupplyChainTransactionHandler { return Err(ApplyError::InvalidTransaction(format!( "Record does not exist: {}", record_id - ))) + ))); } Err(err) => return Err(err), }; @@ -794,7 +804,7 @@ impl SupplyChainTransactionHandler { None => { return Err(ApplyError::InvalidTransaction(String::from( "Owner was not found", - ))) + ))); } }; let custodian = match final_record.custodians.last() { @@ -802,7 +812,7 @@ impl SupplyChainTransactionHandler { None => { return Err(ApplyError::InvalidTransaction(String::from( "Custodian was not found", - ))) + ))); } }; @@ -827,7 +837,7 @@ impl SupplyChainTransactionHandler { fn _create_record_type( &self, - payload: payload::CreateRecordTypeAction, + payload: CreateRecordTypeAction, mut state: SupplyChainState, signer: &str, ) -> Result<(), ApplyError> { @@ -837,12 +847,12 @@ impl SupplyChainTransactionHandler { return Err(ApplyError::InvalidTransaction(format!( "Agent is not register: {}", signer - ))) + ))); } Err(err) => return Err(err), } let name = payload.get_name(); - let mut provided_properties: HashMap<&str, property::PropertySchema> = HashMap::new(); + let mut provided_properties: HashMap<&str, PropertySchema> = HashMap::new(); for property in payload.get_properties() { provided_properties.insert(property.get_name(), property.clone()); } @@ -851,12 +861,12 @@ impl SupplyChainTransactionHandler { return Err(ApplyError::InvalidTransaction(format!( "Record type already exists: {}", signer - ))) + ))); } Ok(None) => (), Err(err) => return Err(err), } - let mut record_type = record::RecordType::new(); + let mut record_type = RecordType::new(); record_type.set_name(name.to_string()); record_type.set_properties(RepeatedField::from_vec(payload.get_properties().to_vec())); @@ -867,7 +877,7 @@ impl SupplyChainTransactionHandler { fn _update_properties( &self, - payload: payload::UpdatePropertiesAction, + payload: UpdatePropertiesAction, mut state: SupplyChainState, signer: &str, timestamp: u64, @@ -879,7 +889,7 @@ impl SupplyChainTransactionHandler { return Err(ApplyError::InvalidTransaction(format!( "Record does not exist: {}", record_id - ))) + ))); } Err(err) => return Err(err), }; @@ -903,7 +913,7 @@ impl SupplyChainTransactionHandler { return Err(ApplyError::InvalidTransaction(format!( "Record does not have provided poperty: {}", name - ))) + ))); } Err(err) => return Err(err), }; @@ -944,20 +954,16 @@ impl SupplyChainTransactionHandler { Ok(None) => { return Err(ApplyError::InvalidTransaction(String::from( "Property page does not exist", - ))) + ))); } Err(err) => return Err(err), }; - let reported_value = match self._make_new_reported_value( - reporter_index, - timestamp, - update, - &prop, - ) { - Ok(reported_value) => reported_value, - Err(err) => return Err(err), - }; + let reported_value = + match self._make_new_reported_value(reporter_index, timestamp, update, &prop) { + Ok(reported_value) => reported_value, + Err(err) => return Err(err), + }; page.reported_values.push(reported_value); page.reported_values .sort_by_key(|rv| (rv.clone().timestamp, rv.clone().reporter_index)); @@ -974,7 +980,7 @@ impl SupplyChainTransactionHandler { new_page } Ok(None) => { - let mut new_page = property::PropertyPage::new(); + let mut new_page = PropertyPage::new(); new_page.set_name(name.to_string()); new_page.set_record_id(record_id.to_string()); new_page @@ -996,7 +1002,7 @@ impl SupplyChainTransactionHandler { fn _create_proposal( &self, - payload: payload::CreateProposalAction, + payload: CreateProposalAction, mut state: SupplyChainState, signer: &str, timestamp: u64, @@ -1012,7 +1018,7 @@ impl SupplyChainTransactionHandler { return Err(ApplyError::InvalidTransaction(format!( "Issuing agent does not exist: {}", signer - ))) + ))); } Err(err) => return Err(err), }; @@ -1023,26 +1029,27 @@ impl SupplyChainTransactionHandler { return Err(ApplyError::InvalidTransaction(format!( "Receiving agent does not exist: {}", receiving_agent - ))) + ))); } Err(err) => return Err(err), }; let mut proposals = match state.get_proposal_container(&record_id, &receiving_agent) { Ok(Some(proposals)) => proposals, - Ok(None) => proposal::ProposalContainer::new(), + Ok(None) => ProposalContainer::new(), Err(err) => return Err(err), }; - let mut open_proposals = Vec::::new(); + let mut open_proposals = Vec::::new(); for prop in proposals.get_entries() { - if prop.status == proposal::Proposal_Status::OPEN { + if prop.status == Proposal_Status::OPEN { open_proposals.push(prop.clone()); } } for prop in open_proposals { - if prop.get_receiving_agent() == receiving_agent && prop.get_role() == role + if prop.get_receiving_agent() == receiving_agent + && prop.get_role() == role && prop.get_record_id() == record_id { return Err(ApplyError::InvalidTransaction(String::from( @@ -1057,7 +1064,7 @@ impl SupplyChainTransactionHandler { return Err(ApplyError::InvalidTransaction(format!( "Record does not exist: {}", record_id - ))) + ))); } Err(err) => return Err(err), }; @@ -1069,13 +1076,13 @@ impl SupplyChainTransactionHandler { ))); } - if role == proposal::Proposal_Role::OWNER || role == proposal::Proposal_Role::REPORTER { + if role == Proposal_Role::OWNER || role == Proposal_Role::REPORTER { let owner = match proposal_record.owners.last() { Some(owner) => owner, None => { return Err(ApplyError::InvalidTransaction(String::from( "Owner not found", - ))) + ))); } }; if owner.get_agent_id() != signer { @@ -1085,13 +1092,13 @@ impl SupplyChainTransactionHandler { } } - if role == proposal::Proposal_Role::CUSTODIAN { + if role == Proposal_Role::CUSTODIAN { let custodian = match proposal_record.custodians.last() { Some(custodian) => custodian, None => { return Err(ApplyError::InvalidTransaction(String::from( "Custodian not found", - ))) + ))); } }; @@ -1102,14 +1109,14 @@ impl SupplyChainTransactionHandler { } } - let mut new_proposal = proposal::Proposal::new(); + let mut new_proposal = Proposal::new(); new_proposal.set_record_id(record_id.to_string()); new_proposal.set_timestamp(timestamp); new_proposal.set_issuing_agent(signer.to_string()); new_proposal.set_receiving_agent(receiving_agent.to_string()); new_proposal.set_role(role); new_proposal.set_properties(properties); - new_proposal.set_status(proposal::Proposal_Status::OPEN); + new_proposal.set_status(Proposal_Status::OPEN); proposals.entries.push(new_proposal); proposals.entries.sort_by_key(|p| { @@ -1126,7 +1133,7 @@ impl SupplyChainTransactionHandler { fn _answer_proposal( &self, - payload: payload::AnswerProposalAction, + payload: AnswerProposalAction, mut state: SupplyChainState, signer: &str, timestamp: u64, @@ -1141,7 +1148,7 @@ impl SupplyChainTransactionHandler { Ok(None) => { return Err(ApplyError::InvalidTransaction(String::from( "Proposal does not exist", - ))) + ))); } Err(err) => return Err(err), }; @@ -1153,7 +1160,7 @@ impl SupplyChainTransactionHandler { return Err(ApplyError::InvalidTransaction(format!( "No open proposals found for record {} for {}", record_id, receiving_agent - ))) + ))); } }; @@ -1161,9 +1168,10 @@ impl SupplyChainTransactionHandler { let mut count = 0; for prop in proposals.get_entries() { - if prop.get_receiving_agent() == receiving_agent && prop.get_role() == role + if prop.get_receiving_agent() == receiving_agent + && prop.get_role() == role && prop.get_record_id() == record_id - && prop.status == proposal::Proposal_Status::OPEN + && prop.status == Proposal_Status::OPEN { current_proposal = prop.clone(); exists = true; @@ -1181,23 +1189,23 @@ impl SupplyChainTransactionHandler { } match response { - payload::AnswerProposalAction_Response::CANCEL => { + AnswerProposalAction_Response::CANCEL => { if current_proposal.get_issuing_agent() != signer { return Err(ApplyError::InvalidTransaction(String::from( "Only the issuing agent can cancel a proposal", ))); } - current_proposal.status = proposal::Proposal_Status::CANCELED; + current_proposal.status = Proposal_Status::CANCELED; } - payload::AnswerProposalAction_Response::REJECT => { + AnswerProposalAction_Response::REJECT => { if current_proposal.get_receiving_agent() != signer { return Err(ApplyError::InvalidTransaction(String::from( "Only the receiving agent can reject a proposal", ))); } - current_proposal.status = proposal::Proposal_Status::REJECTED; + current_proposal.status = Proposal_Status::REJECTED; } - payload::AnswerProposalAction_Response::ACCEPT => { + AnswerProposalAction_Response::ACCEPT => { if current_proposal.get_receiving_agent() != signer { return Err(ApplyError::InvalidTransaction(String::from( "Only the receiving agent can Accept a proposal", @@ -1210,7 +1218,7 @@ impl SupplyChainTransactionHandler { return Err(ApplyError::InvalidTransaction(format!( "Record in proposal does not exist: {}", record_id - ))) + ))); } Err(err) => return Err(err), }; @@ -1220,7 +1228,7 @@ impl SupplyChainTransactionHandler { None => { return Err(ApplyError::InvalidTransaction(String::from( "Owner not found", - ))) + ))); } }; @@ -1229,14 +1237,14 @@ impl SupplyChainTransactionHandler { None => { return Err(ApplyError::InvalidTransaction(String::from( "Custodian not found", - ))) + ))); } }; match role { - proposal::Proposal_Role::OWNER => { + Proposal_Role::OWNER => { if owner.get_agent_id() != current_proposal.get_issuing_agent() { - current_proposal.status = proposal::Proposal_Status::CANCELED; + current_proposal.status = Proposal_Status::CANCELED; info!("Record owner does not match the issuing agent of the proposal"); // remove old proposal and replace with new one proposals.entries.remove(proposal_index); @@ -1248,11 +1256,15 @@ impl SupplyChainTransactionHandler { p.clone().timestamp, ) }); - state.set_proposal_container(&record_id, &receiving_agent, proposals)?; + state.set_proposal_container( + &record_id, + &receiving_agent, + proposals, + )?; return Ok(()); } - let mut new_owner = record::Record_AssociatedAgent::new(); + let mut new_owner = Record_AssociatedAgent::new(); new_owner.set_agent_id(receiving_agent.to_string()); new_owner.set_timestamp(timestamp); proposal_record.owners.push(new_owner); @@ -1265,7 +1277,7 @@ impl SupplyChainTransactionHandler { return Err(ApplyError::InvalidTransaction(format!( "RecordType does not exist: {}", proposal_record.get_record_type() - ))) + ))); } Err(err) => return Err(err), }; @@ -1277,15 +1289,13 @@ impl SupplyChainTransactionHandler { Ok(None) => { return Err(ApplyError::InvalidTransaction(String::from( "Property does not exist", - ))) + ))); } Err(err) => return Err(err), }; let mut authorized = false; - let mut new_reporters: Vec< - property::Property_Reporter, - > = Vec::new(); + let mut new_reporters: Vec = Vec::new(); let temp_prob = prop.clone(); let reporters = temp_prob.get_reporters(); for reporter in reporters { @@ -1304,7 +1314,7 @@ impl SupplyChainTransactionHandler { } if !authorized { - let mut reporter = property::Property_Reporter::new(); + let mut reporter = Property_Reporter::new(); reporter.set_public_key(receiving_agent.to_string()); reporter.set_authorized(true); reporter.set_index(prop.reporters.len() as u32); @@ -1314,11 +1324,11 @@ impl SupplyChainTransactionHandler { prop.set_reporters(RepeatedField::from_vec(new_reporters)); state.set_property(record_id, prop.get_name(), prop.clone())?; } - current_proposal.status = proposal::Proposal_Status::ACCEPTED; + current_proposal.status = Proposal_Status::ACCEPTED; } - proposal::Proposal_Role::CUSTODIAN => { + Proposal_Role::CUSTODIAN => { if custodian.get_agent_id() != current_proposal.get_issuing_agent() { - current_proposal.status = proposal::Proposal_Status::CANCELED; + current_proposal.status = Proposal_Status::CANCELED; info!( "Record custodian does not match the issuing agent of the proposal" ); @@ -1339,16 +1349,16 @@ impl SupplyChainTransactionHandler { )?; } - let mut new_custodian = record::Record_AssociatedAgent::new(); + let mut new_custodian = Record_AssociatedAgent::new(); new_custodian.set_agent_id(receiving_agent.to_string()); new_custodian.set_timestamp(timestamp); proposal_record.custodians.push(new_custodian.clone()); state.set_record(record_id, proposal_record)?; - current_proposal.status = proposal::Proposal_Status::ACCEPTED; + current_proposal.status = Proposal_Status::ACCEPTED; } - proposal::Proposal_Role::REPORTER => { + Proposal_Role::REPORTER => { if owner.get_agent_id() != current_proposal.get_issuing_agent() { - current_proposal.status = proposal::Proposal_Status::CANCELED; + current_proposal.status = Proposal_Status::CANCELED; info!("Record owner does not match the issuing agent of the proposal"); // remove old proposal and replace with new one proposals.entries.remove(proposal_index); @@ -1360,11 +1370,15 @@ impl SupplyChainTransactionHandler { p.clone().timestamp, ) }); - state.set_proposal_container(&record_id, &receiving_agent, proposals)?; + state.set_proposal_container( + &record_id, + &receiving_agent, + proposals, + )?; return Ok(()); } - let mut reporter = property::Property_Reporter::new(); + let mut reporter = Property_Reporter::new(); reporter.set_public_key(receiving_agent.to_string()); reporter.set_authorized(true); @@ -1374,7 +1388,7 @@ impl SupplyChainTransactionHandler { Ok(None) => { return Err(ApplyError::InvalidTransaction(String::from( "Property does not exist", - ))) + ))); } Err(err) => return Err(err), }; @@ -1382,7 +1396,7 @@ impl SupplyChainTransactionHandler { prop.reporters.push(reporter.clone()); state.set_property(record_id, prop_name, prop)?; } - current_proposal.status = proposal::Proposal_Status::ACCEPTED; + current_proposal.status = Proposal_Status::ACCEPTED; } } } @@ -1404,7 +1418,7 @@ impl SupplyChainTransactionHandler { fn _revoke_reporter( &self, - payload: payload::RevokeReporterAction, + payload: RevokeReporterAction, mut state: SupplyChainState, signer: &str, ) -> Result<(), ApplyError> { @@ -1418,7 +1432,7 @@ impl SupplyChainTransactionHandler { return Err(ApplyError::InvalidTransaction(format!( "Record does not exists: {}", record_id - ))) + ))); } Err(err) => return Err(err), }; @@ -1428,7 +1442,7 @@ impl SupplyChainTransactionHandler { None => { return Err(ApplyError::InvalidTransaction(String::from( "Owner was not found", - ))) + ))); } }; @@ -1451,12 +1465,12 @@ impl SupplyChainTransactionHandler { Ok(None) => { return Err(ApplyError::InvalidTransaction(format!( "Property does not exists" - ))) + ))); } Err(err) => return Err(err), }; - let mut new_reporters: Vec = Vec::new(); + let mut new_reporters: Vec = Vec::new(); let mut revoked = false; for reporter in prop.get_reporters() { if reporter.get_public_key() == reporter_id { @@ -1491,50 +1505,52 @@ impl SupplyChainTransactionHandler { &self, reporter_index: u32, timestamp: u64, - value: &property::PropertyValue, - property: &property::Property, - ) -> Result { - let mut reported_value = property::PropertyPage_ReportedValue::new(); + value: &PropertyValue, + property: &Property, + ) -> Result { + let mut reported_value = PropertyPage_ReportedValue::new(); reported_value.set_reporter_index(reporter_index); reported_value.set_timestamp(timestamp); match value.get_data_type() { - property::PropertySchema_DataType::TYPE_UNSET => { + PropertySchema_DataType::TYPE_UNSET => { return Err(ApplyError::InvalidTransaction(String::from( "DataType is not set", - ))) + ))); } - property::PropertySchema_DataType::BYTES => { + PropertySchema_DataType::BYTES => { reported_value.set_bytes_value(value.get_bytes_value().to_vec()) } - property::PropertySchema_DataType::BOOLEAN => { + PropertySchema_DataType::BOOLEAN => { reported_value.set_boolean_value(value.get_boolean_value()) } - property::PropertySchema_DataType::NUMBER => { + PropertySchema_DataType::NUMBER => { reported_value.set_number_value(value.get_number_value()) } - property::PropertySchema_DataType::STRING => { + PropertySchema_DataType::STRING => { reported_value.set_string_value(value.get_string_value().to_string()) } - property::PropertySchema_DataType::ENUM => { + PropertySchema_DataType::ENUM => { let enum_name = value.get_enum_value().to_string(); - let enum_index = match property.enum_options.iter() - .position(|name| name == &enum_name) { - Some(index) => index, - None => { - return Err(ApplyError::InvalidTransaction(format!( - "Provided enum name is not a valid option: {}", - enum_name, - ))) - } - }; + let enum_index = match property + .enum_options + .iter() + .position(|name| name == &enum_name) + { + Some(index) => index, + None => { + return Err(ApplyError::InvalidTransaction(format!( + "Provided enum name is not a valid option: {}", + enum_name, + ))); + } + }; reported_value.set_enum_value(enum_index as u32) } - property::PropertySchema_DataType::STRUCT => { - match self._validate_struct_values( - &value.struct_values, - &property.struct_properties - ) { + PropertySchema_DataType::STRUCT => { + match self + ._validate_struct_values(&value.struct_values, &property.struct_properties) + { Ok(_) => (), Err(e) => return Err(e), } @@ -1542,7 +1558,7 @@ impl SupplyChainTransactionHandler { let struct_values = RepeatedField::from_vec(value.get_struct_values().to_vec()); reported_value.set_struct_values(struct_values) } - property::PropertySchema_DataType::LOCATION => { + PropertySchema_DataType::LOCATION => { reported_value.set_location_value(value.get_location_value().clone()) } }; @@ -1551,39 +1567,38 @@ impl SupplyChainTransactionHandler { fn _validate_struct_values( &self, - struct_values: &RepeatedField, - schema_values: &RepeatedField + struct_values: &RepeatedField, + schema_values: &RepeatedField, ) -> Result<(), ApplyError> { if struct_values.len() != schema_values.len() { return Err(ApplyError::InvalidTransaction(format!( "Provided struct does not match schema length: {:?} != {:?}", struct_values.len(), schema_values.len(), - ))) + ))); } for schema in schema_values.iter() { let value = match struct_values.iter().find(|val| val.name == schema.name) { Some(val) => val, - None => return Err(ApplyError::InvalidTransaction(format!( - "Provided struct missing required property from schema: {}", - schema.name, - ))) + None => { + return Err(ApplyError::InvalidTransaction(format!( + "Provided struct missing required property from schema: {}", + schema.name, + ))); + } }; if value.data_type != schema.data_type { return Err(ApplyError::InvalidTransaction(format!( "Struct property \"{}\" must have data type: {:?}", - schema.name, - schema.data_type, - ))) + schema.name, schema.data_type, + ))); } - if schema.data_type == property::PropertySchema_DataType::STRUCT { - match self._validate_struct_values( - &value.struct_values, - &schema.struct_properties - ) { + if schema.data_type == PropertySchema_DataType::STRUCT { + match self._validate_struct_values(&value.struct_values, &schema.struct_properties) + { Ok(_) => (), Err(e) => return Err(e), } @@ -1622,7 +1637,7 @@ impl TransactionHandler for SupplyChainTransactionHandler { None => { return Err(ApplyError::InvalidTransaction(String::from( "Request must contain a payload", - ))) + ))); } }; diff --git a/contracts/track_and_trace/src/main.rs b/contracts/track_and_trace/src/main.rs index 3e32919f7d..898f113231 100644 --- a/contracts/track_and_trace/src/main.rs +++ b/contracts/track_and_trace/src/main.rs @@ -18,19 +18,19 @@ extern crate crypto; extern crate log4rs; #[macro_use] extern crate log; +extern crate grid_sdk; extern crate protobuf; extern crate rustc_serialize; extern crate sawtooth_sdk; -mod handler; mod addressing; -mod messages; +mod handler; -use std::process; use log::LogLevelFilter; use log4rs::append::console::ConsoleAppender; use log4rs::config::{Appender, Config, Root}; use log4rs::encode::pattern::PatternEncoder; +use std::process; use sawtooth_sdk::processor::TransactionProcessor; @@ -44,7 +44,7 @@ fn main() { "connection endpoint for validator") (@arg verbose: -v --verbose +multiple "increase output verbosity")) - .get_matches(); + .get_matches(); let endpoint = matches .value_of("connect") diff --git a/docker-compose.yaml b/docker-compose.yaml index fe621eaa15..e9cd6363c1 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -21,7 +21,8 @@ services: image: grid-track-and-trace-tp container_name: grid-track-and-trace-tp build: - context: contracts/track_and_trace/ + context: . + dockerfile: contracts/track_and_trace/Dockerfile args: - http_proxy - https_proxy @@ -32,6 +33,7 @@ services: - 'no_proxy=rest-api,eth0,validator,${no_proxy}' volumes: - .:/grid + - /grid/sdk - /grid/contracts/track_and_trace/target - /grid/contracts/track_and_trace/src/messages entrypoint: | diff --git a/protos/agent.proto b/protos/agent.proto deleted file mode 100644 index b9713d26f1..0000000000 --- a/protos/agent.proto +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright 2017 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. -// ----------------------------------------------------------------------------- - -syntax = "proto3"; - - -message Agent { - string public_key = 1; - - // A human readable name identifying the Agent - string name = 2; - - // Unix UTC timestamp of approximately when this agent was registered - uint64 timestamp = 3; -} - - -message AgentContainer { - repeated Agent entries = 1; -} diff --git a/protos/payload.proto b/protos/payload.proto deleted file mode 100644 index 196af36143..0000000000 --- a/protos/payload.proto +++ /dev/null @@ -1,137 +0,0 @@ -// Copyright 2017 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. -// ----------------------------------------------------------------------------- - -syntax = "proto3"; - -import "property.proto"; -import "proposal.proto"; - - -message SCPayload { - enum Action { - CREATE_AGENT = 0; - CREATE_RECORD = 1; - FINALIZE_RECORD = 2; - CREATE_RECORD_TYPE = 3; - UPDATE_PROPERTIES = 4; - CREATE_PROPOSAL = 5; - ANSWER_PROPOSAL = 6; - REVOKE_REPORTER = 7; - } - - Action action = 1; - - // Approximately when transaction was submitted, as a Unix UTC - // timestamp - uint64 timestamp = 2; - - // The transaction handler will read from just one of these fields - // according to the Action. - CreateAgentAction create_agent = 3; - CreateRecordAction create_record = 4; - FinalizeRecordAction finalize_record = 5; - CreateRecordTypeAction create_record_type = 6; - UpdatePropertiesAction update_properties = 7; - CreateProposalAction create_proposal = 8; - AnswerProposalAction answer_proposal = 9; - RevokeReporterAction revoke_reporter = 10; -} - - -message CreateAgentAction { - // The human-readable name of the Agent. This does not need to be - // unique. - string name = 1; -} - - -message CreateRecordAction { - // The natural key of the Record - string record_id = 1; - - // The name of the RecordType this Record belongs to - string record_type = 2; - - repeated PropertyValue properties = 3; -} - - -message FinalizeRecordAction { - // The natural key of the Record - string record_id = 1; -} - - -message CreateRecordTypeAction { - string name = 1; - - repeated PropertySchema properties = 2; -} - - -message UpdatePropertiesAction { - // The natural key of the Record - string record_id = 1; - - repeated PropertyValue properties = 2; -} - - -message CreateProposalAction { - // The natural key of the Record - string record_id = 1; - - // the public key of the Agent to whom the Proposal is sent - // (must be different from the Agent creating the Proposal) - string receiving_agent = 2; - - Proposal.Role role = 3; - - repeated string properties = 4; -} - - -message AnswerProposalAction { - enum Response { - ACCEPT = 0; - REJECT = 1; - CANCEL = 2; - } - - // The natural key of the Record - string record_id = 1; - - // The public key of the Agent to whom the proposal is sent - string receiving_agent = 2; - - // The role being proposed (owner, custodian, or reporter) - Proposal.Role role = 3; - - // The respose to the Proposal (accept, reject, or cancel) - Response response = 4; -} - - -message RevokeReporterAction { - // The natural key of the Record - string record_id = 1; - - // The reporter's public key - string reporter_id = 2; - - // The names of the Properties for which the reporter's - // authorization is revoked - repeated string properties = 3; -} diff --git a/protos/property.proto b/protos/property.proto deleted file mode 100644 index 13c7ecad69..0000000000 --- a/protos/property.proto +++ /dev/null @@ -1,193 +0,0 @@ -// Copyright 2017 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. -// ----------------------------------------------------------------------------- - -syntax = "proto3"; - - -message Property { - message Reporter { - // The public key of the Agent authorized to report updates. - string public_key = 1; - bool authorized = 2; - // An update must be stored with some way of identifying which - // Agent sent it. Storing a full public key for each update would - // be wasteful, so instead Reporters are identified by their index - // in the `reporters` field. - uint32 index = 3; - } - - // The name of the Property, e.g. "temperature". This must be unique - // among Properties. - string name = 1; - - // The natural key of the Property's associated Record. - string record_id = 2; - - // The Property's type (int, string, etc.) - PropertySchema.DataType data_type = 3; - - // The Reporters authorized to send updates, sorted by index. New - // Reporters should be given an index equal to the number of - // Reporters already authorized. - repeated Reporter reporters = 4; - - // The page to which new updates are added. This number represents - // the last 4 hex characters of the page's address. Consequently, - // it should not exceed 16^4 = 65536. - uint32 current_page = 5; - - // A flag indicating whether the first 16^4 pages have been filled. - // This is used to calculate the last four hex characters of the - // address of the page containing the earliest updates. When it is - // false, the earliest page's address will end in "0001". When it is - // true, the earliest page's address will be one more than the - // current_page, or "0001" if the current_page is "ffff". - bool wrapped = 6; - - // If set to true, values may only be set for this Property - // during Record creation, not later with updates. - bool fixed = 9; - - // Used with numbers to communicate how the integer value should be converted - // to a fractional number. Uses the same principle as scientific notation. - // A number value of 1, with an exponent of 3, would be 1,000 (1 * 10^3). - // A number value of 1, with an exponent of -3, would be 0.001 (1 * 10^-3). - sint32 number_exponent = 10; - - // Used with ENUM data types, the string names of available options - repeated string enum_options = 11; - - // Used with STRUCT data types, defines the properties a struct must contain - repeated PropertySchema struct_properties = 12; - - // This optional metadata describes the unit a Property is measured in - string unit = 20; -} - - -message PropertyContainer { - repeated Property entries = 1; -} - - -message PropertySchema { - enum DataType { - TYPE_UNSET = 0; - BYTES = 1; - BOOLEAN = 2; - NUMBER = 3; - STRING = 4; - ENUM = 5; - STRUCT = 6; - LOCATION = 7; - } - - // The name of the property, e.g. "temperature" - string name = 1; - - // The Property's type (int, string, etc.) - DataType data_type = 2; - - // A flag indicating whether initial values must be provided for the - // Property when a Record is created. - bool required = 3; - - // Another flag. If set to true, values may only be set for this Property - // during Record creation, not later with updates. - bool fixed = 4; - - // A flag that indicates a property may not be set at record creation, - // only later during subsequent property updates. - bool delayed = 5; - - // Used with numbers to communicate how the integer value should be converted - // to a fractional number. Uses the same principle as scientific notation. - // A number value of 1, with an exponent of 3, would be 1,000 (1 * 10^3). - // A number value of 1, with an exponent of -3, would be 0.001 (1 * 10^-3). - sint32 number_exponent = 10; - - // Used with ENUM data types, the string names of available options - repeated string enum_options = 11; - - // Used with STRUCT data types, defines the properties a struct must contain - repeated PropertySchema struct_properties = 12; - - // This optional metadata describes the unit a Property is measured in - string unit = 20; -} - - -message PropertyValue { - // The name of the property being set - string name = 1; - - // The PropertyValue's type (int, string, etc.) - PropertySchema.DataType data_type = 2; - - // The type-specific value to initialize or update a Property. Only - // one of these fields should be used, and it should match the type - // specified for this Property in the RecordType. - bytes bytes_value = 11; - bool boolean_value = 12; - sint64 number_value = 13; - string string_value = 14; - string enum_value = 15; - repeated PropertyValue struct_values = 16; - Location location_value = 17; -} - - -message PropertyPage { - message ReportedValue { - // The index of the reporter id in reporters field - uint32 reporter_index = 1; - // Approximately when this value was reported, as a Unix UTC - // timestamp - uint64 timestamp = 2; - - // The type-specific value of the update. Only one of these - // fields should be used, and it should match the type - // specified for this Property in the RecordType. - bytes bytes_value = 11; - bool boolean_value = 12; - sint64 number_value = 13; - string string_value = 14; - uint32 enum_value = 15; - repeated PropertyValue struct_values = 16; - Location location_value = 17; - } - - // The name of the page's associated Property and the record_id of - // its associated Record. These are required to distinguish pages - // with colliding addresses. - string name = 1; - string record_id = 2; - - // ReportedValues are sorted first by timestamp, then by - // reporter_index - repeated ReportedValue reported_values = 3; -} - - -message PropertyPageContainer { - repeated PropertyPage entries = 1; -} - - -message Location { - // Coordinates are expected to be in millionths of a degree - sint64 latitude = 1; - sint64 longitude = 2; -} diff --git a/protos/proposal.proto b/protos/proposal.proto deleted file mode 100644 index 59d909031b..0000000000 --- a/protos/proposal.proto +++ /dev/null @@ -1,66 +0,0 @@ -// Copyright 2017 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. -// ----------------------------------------------------------------------------- - -syntax = "proto3"; - - -message Proposal { - enum Role { - OWNER = 0; - CUSTODIAN = 1; - REPORTER = 2; - } - - enum Status { - OPEN = 0; - ACCEPTED = 1; - REJECTED = 2; - CANCELED = 3; - } - - string record_id = 1; - - // The time at which the Proposal was created - uint64 timestamp = 2; - - // The public key of the Agent sending the Proposal. This Agent must - // be the owner of the Record (or the custodian, if the Proposal is - // to transfer custodianship). - string issuing_agent = 3; - - // The public key of the Agent to whom the Proposal is sent. - string receiving_agent = 4; - - // What the Proposal is for -- transferring ownership, transferring - // custodianship, or authorizing a reporter. - Role role = 5; - - // The names of properties for which the reporter is being authorized - // (empty for owner or custodian transfers) - repeated string properties = 6; - - // The status of the Proposal. For a given Record and receiving - // Agent, there can be only one open Proposal at a time for each - // role. - Status status = 7; - - // The human-readable terms of transfer. - string terms = 8; -} - - -message ProposalContainer { - repeated Proposal entries = 1; -} diff --git a/protos/record.proto b/protos/record.proto deleted file mode 100644 index fabea61c40..0000000000 --- a/protos/record.proto +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright 2017 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. -// ----------------------------------------------------------------------------- - -syntax = "proto3"; - -import "property.proto"; - - -message Record { - message AssociatedAgent { - string agent_id = 1; - uint64 timestamp = 2; - } - - // The user-defined natural key which identifies the object in the - // real world (for example a serial number) - string record_id = 1; - - string record_type = 2; - - // Ordered oldest to newest by timestamp - repeated AssociatedAgent owners = 3; - repeated AssociatedAgent custodians = 4; - - // Flag indicating whether the Record can be updated. If it is set - // to true, then the record has been finalized and no further - // changes can be made to it or its Properties. - bool final = 5; -} - - -message RecordContainer { - repeated Record entries = 1; -} - - -message RecordType { - // A unique human-readable designation for the RecordType - string name = 1; - - repeated PropertySchema properties = 2; -} - - -message RecordTypeContainer { - repeated RecordType entries = 1; -} From 4085f4138b9899bfc8510bc2e371a328382b194c Mon Sep 17 00:00:00 2001 From: Andrea Gunderson Date: Mon, 18 Mar 2019 18:53:03 -0500 Subject: [PATCH 3/3] Add verbose logging track and trace tp in docker-compose Signed-off-by: Andrea Gunderson --- docker-compose-installed.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker-compose-installed.yaml b/docker-compose-installed.yaml index bd5a640437..7377d96100 100644 --- a/docker-compose-installed.yaml +++ b/docker-compose-installed.yaml @@ -29,7 +29,7 @@ services: - no_proxy depends_on: - validator - entrypoint: grid-track-and-trace-tp -C tcp://validator:4004 + entrypoint: grid-track-and-trace-tp -C tcp://validator:4004 -v validator: image: hyperledger/sawtooth-validator:1.0