diff --git a/Cargo.lock b/Cargo.lock
index 7e49d98..459f186 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1923,6 +1923,7 @@ dependencies = [
name = "secret-sdk-proto"
version = "0.1.0"
dependencies = [
+ "bumpalo",
"cosmos-sdk-proto",
"getrandom",
"prost",
@@ -1932,7 +1933,7 @@ dependencies = [
[[package]]
name = "secret-utils"
-version = "0.1.0"
+version = "0.0.0"
dependencies = [
"aes-siv",
"async-trait",
@@ -1956,20 +1957,29 @@ dependencies = [
[[package]]
name = "secretrs"
-version = "0.0.1"
+version = "0.0.0"
dependencies = [
+ "aes-siv",
+ "async-trait",
"base64 0.22.0",
+ "bip32",
+ "bip39",
"color-eyre",
"cosmrs",
"hex",
+ "hkdf",
+ "nanorand",
"regex",
+ "secret-cosmwasm-std",
"secret-sdk-proto",
- "secret-utils",
"serde",
"serde_json",
+ "sha2 0.10.8",
+ "thiserror",
"tokio",
"tonic",
"tonic-web-wasm-client",
+ "x25519-dalek",
]
[[package]]
diff --git a/Cargo.toml b/Cargo.toml
index 3da6692..d5ddc0b 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,7 +1,7 @@
[workspace]
resolver = "2"
-members = ["secret-sdk-proto", "secret-grpc", "secretrs", "secret-utils"]
-exclude = ["proto-build"]
+members = ["secret-sdk-proto", "secret-grpc", "secretrs"]
+exclude = ["proto-build", "secret-utils"]
# This patch adds target_arch = "wasm32" configurations to the rpc clients
[patch.crates-io]
diff --git a/LICENSE b/LICENSE
deleted file mode 100644
index 261eeb9..0000000
--- a/LICENSE
+++ /dev/null
@@ -1,201 +0,0 @@
- Apache License
- Version 2.0, January 2004
- http://www.apache.org/licenses/
-
- TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
- 1. Definitions.
-
- "License" shall mean the terms and conditions for use, reproduction,
- and distribution as defined by Sections 1 through 9 of this document.
-
- "Licensor" shall mean the copyright owner or entity authorized by
- the copyright owner that is granting the License.
-
- "Legal Entity" shall mean the union of the acting entity and all
- other entities that control, are controlled by, or are under common
- control with that entity. For the purposes of this definition,
- "control" means (i) the power, direct or indirect, to cause the
- direction or management of such entity, whether by contract or
- otherwise, or (ii) ownership of fifty percent (50%) or more of the
- outstanding shares, or (iii) beneficial ownership of such entity.
-
- "You" (or "Your") shall mean an individual or Legal Entity
- exercising permissions granted by this License.
-
- "Source" form shall mean the preferred form for making modifications,
- including but not limited to software source code, documentation
- source, and configuration files.
-
- "Object" form shall mean any form resulting from mechanical
- transformation or translation of a Source form, including but
- not limited to compiled object code, generated documentation,
- and conversions to other media types.
-
- "Work" shall mean the work of authorship, whether in Source or
- Object form, made available under the License, as indicated by a
- copyright notice that is included in or attached to the work
- (an example is provided in the Appendix below).
-
- "Derivative Works" shall mean any work, whether in Source or Object
- form, that is based on (or derived from) the Work and for which the
- editorial revisions, annotations, elaborations, or other modifications
- represent, as a whole, an original work of authorship. For the purposes
- of this License, Derivative Works shall not include works that remain
- separable from, or merely link (or bind by name) to the interfaces of,
- the Work and Derivative Works thereof.
-
- "Contribution" shall mean any work of authorship, including
- the original version of the Work and any modifications or additions
- to that Work or Derivative Works thereof, that is intentionally
- submitted to Licensor for inclusion in the Work by the copyright owner
- or by an individual or Legal Entity authorized to submit on behalf of
- the copyright owner. For the purposes of this definition, "submitted"
- means any form of electronic, verbal, or written communication sent
- to the Licensor or its representatives, including but not limited to
- communication on electronic mailing lists, source code control systems,
- and issue tracking systems that are managed by, or on behalf of, the
- Licensor for the purpose of discussing and improving the Work, but
- excluding communication that is conspicuously marked or otherwise
- designated in writing by the copyright owner as "Not a Contribution."
-
- "Contributor" shall mean Licensor and any individual or Legal Entity
- on behalf of whom a Contribution has been received by Licensor and
- subsequently incorporated within the Work.
-
- 2. Grant of Copyright License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- copyright license to reproduce, prepare Derivative Works of,
- publicly display, publicly perform, sublicense, and distribute the
- Work and such Derivative Works in Source or Object form.
-
- 3. Grant of Patent License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- (except as stated in this section) patent license to make, have made,
- use, offer to sell, sell, import, and otherwise transfer the Work,
- where such license applies only to those patent claims licensable
- by such Contributor that are necessarily infringed by their
- Contribution(s) alone or by combination of their Contribution(s)
- with the Work to which such Contribution(s) was submitted. If You
- institute patent litigation against any entity (including a
- cross-claim or counterclaim in a lawsuit) alleging that the Work
- or a Contribution incorporated within the Work constitutes direct
- or contributory patent infringement, then any patent licenses
- granted to You under this License for that Work shall terminate
- as of the date such litigation is filed.
-
- 4. Redistribution. You may reproduce and distribute copies of the
- Work or Derivative Works thereof in any medium, with or without
- modifications, and in Source or Object form, provided that You
- meet the following conditions:
-
- (a) You must give any other recipients of the Work or
- Derivative Works a copy of this License; and
-
- (b) You must cause any modified files to carry prominent notices
- stating that You changed the files; and
-
- (c) You must retain, in the Source form of any Derivative Works
- that You distribute, all copyright, patent, trademark, and
- attribution notices from the Source form of the Work,
- excluding those notices that do not pertain to any part of
- the Derivative Works; and
-
- (d) If the Work includes a "NOTICE" text file as part of its
- distribution, then any Derivative Works that You distribute must
- include a readable copy of the attribution notices contained
- within such NOTICE file, excluding those notices that do not
- pertain to any part of the Derivative Works, in at least one
- of the following places: within a NOTICE text file distributed
- as part of the Derivative Works; within the Source form or
- documentation, if provided along with the Derivative Works; or,
- within a display generated by the Derivative Works, if and
- wherever such third-party notices normally appear. The contents
- of the NOTICE file are for informational purposes only and
- do not modify the License. You may add Your own attribution
- notices within Derivative Works that You distribute, alongside
- or as an addendum to the NOTICE text from the Work, provided
- that such additional attribution notices cannot be construed
- as modifying the License.
-
- You may add Your own copyright statement to Your modifications and
- may provide additional or different license terms and conditions
- for use, reproduction, or distribution of Your modifications, or
- for any such Derivative Works as a whole, provided Your use,
- reproduction, and distribution of the Work otherwise complies with
- the conditions stated in this License.
-
- 5. Submission of Contributions. Unless You explicitly state otherwise,
- any Contribution intentionally submitted for inclusion in the Work
- by You to the Licensor shall be under the terms and conditions of
- this License, without any additional terms or conditions.
- Notwithstanding the above, nothing herein shall supersede or modify
- the terms of any separate license agreement you may have executed
- with Licensor regarding such Contributions.
-
- 6. Trademarks. This License does not grant permission to use the trade
- names, trademarks, service marks, or product names of the Licensor,
- except as required for reasonable and customary use in describing the
- origin of the Work and reproducing the content of the NOTICE file.
-
- 7. Disclaimer of Warranty. Unless required by applicable law or
- agreed to in writing, Licensor provides the Work (and each
- Contributor provides its Contributions) on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- implied, including, without limitation, any warranties or conditions
- of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
- PARTICULAR PURPOSE. You are solely responsible for determining the
- appropriateness of using or redistributing the Work and assume any
- risks associated with Your exercise of permissions under this License.
-
- 8. Limitation of Liability. In no event and under no legal theory,
- whether in tort (including negligence), contract, or otherwise,
- unless required by applicable law (such as deliberate and grossly
- negligent acts) or agreed to in writing, shall any Contributor be
- liable to You for damages, including any direct, indirect, special,
- incidental, or consequential damages of any character arising as a
- result of this License or out of the use or inability to use the
- Work (including but not limited to damages for loss of goodwill,
- work stoppage, computer failure or malfunction, or any and all
- other commercial damages or losses), even if such Contributor
- has been advised of the possibility of such damages.
-
- 9. Accepting Warranty or Additional Liability. While redistributing
- the Work or Derivative Works thereof, You may choose to offer,
- and charge a fee for, acceptance of support, warranty, indemnity,
- or other liability obligations and/or rights consistent with this
- License. However, in accepting such obligations, You may act only
- on Your own behalf and on Your sole responsibility, not on behalf
- of any other Contributor, and only if You agree to indemnify,
- defend, and hold each Contributor harmless for any liability
- incurred by, or claims asserted against, such Contributor by reason
- of your accepting any such warranty or additional liability.
-
- END OF TERMS AND CONDITIONS
-
- APPENDIX: How to apply the Apache License to your work.
-
- To apply the Apache License to your work, attach the following
- boilerplate notice, with the fields enclosed by brackets "[]"
- replaced with your own identifying information. (Don't include
- the brackets!) The text should be enclosed in the appropriate
- comment syntax for the file format. We also recommend that a
- file or class name and description of purpose be included on the
- same "printed page" as the copyright notice for easier
- identification within third-party archives.
-
- Copyright [yyyy] [name of copyright owner]
-
- 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.
diff --git a/README.md b/README.md
index 99562df..2d0f41f 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,10 @@
+
+
+
+
# Secret Rust
-_Insert cool description here._
+An extension of [Cosmos Rust](https://github.com/cosmos/cosmos-rust) for [Secret](https://github.com/scrtlabs/SecretNetwork).
## Crates
@@ -20,8 +24,7 @@ _Insert cool description here._
- [x] `proto-build` crate like cosmos-rust and tendermint-rs each have
- [x] `secret-sdk-proto` crate that re-exports `cosmos-sdk-proto` and adds secret protobuf structs
-- [x] `secretrs` crate that re-exports `cosmrs` and adds secret type conversions
- - [x] `secret-utils` provide encryption and decryption tools for use with any client
+- [x] `secretrs` crate that re-exports `cosmrs` and adds secret types, encryption tools
- [ ] `secret-grpc` crate with full gRPC client implementation
- [ ] `secret-grpc-gateway` crate with full gRPC-gateway (REST) client implementation
diff --git a/UNLICENSE b/UNLICENSE
new file mode 100644
index 0000000..b3dbff0
--- /dev/null
+++ b/UNLICENSE
@@ -0,0 +1,22 @@
+This is free and unencumbered software released into the public domain.
+
+Anyone is free to copy, modify, publish, use, compile, sell, or
+distribute this software, either in source code form or as a compiled
+binary, for any purpose, commercial or non-commercial, and by any
+means.
+
+In jurisdictions that recognize copyright laws, the author or authors
+of this software dedicate any and all copyright interest in the
+software to the public domain. We make this dedication for the benefit
+of the public at large and to the detriment of our heirs and
+successors. We intend this dedication to be an overt act of
+relinquishment in perpetuity of all present and future rights to this
+software under copyright law.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
diff --git a/banner.webp b/banner.webp
new file mode 100644
index 0000000..6ba5a11
Binary files /dev/null and b/banner.webp differ
diff --git a/secret-grpc/Cargo.toml b/secret-grpc/Cargo.toml
index 91c1a54..f033200 100644
--- a/secret-grpc/Cargo.toml
+++ b/secret-grpc/Cargo.toml
@@ -2,6 +2,7 @@
name = "secret-grpc"
version = "0.1.0"
authors = ["Kent"]
+license = "Unlicense"
edition = "2021"
publish = false
diff --git a/secret-grpc/LICENSE b/secret-grpc/LICENSE
deleted file mode 100644
index 261eeb9..0000000
--- a/secret-grpc/LICENSE
+++ /dev/null
@@ -1,201 +0,0 @@
- Apache License
- Version 2.0, January 2004
- http://www.apache.org/licenses/
-
- TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
- 1. Definitions.
-
- "License" shall mean the terms and conditions for use, reproduction,
- and distribution as defined by Sections 1 through 9 of this document.
-
- "Licensor" shall mean the copyright owner or entity authorized by
- the copyright owner that is granting the License.
-
- "Legal Entity" shall mean the union of the acting entity and all
- other entities that control, are controlled by, or are under common
- control with that entity. For the purposes of this definition,
- "control" means (i) the power, direct or indirect, to cause the
- direction or management of such entity, whether by contract or
- otherwise, or (ii) ownership of fifty percent (50%) or more of the
- outstanding shares, or (iii) beneficial ownership of such entity.
-
- "You" (or "Your") shall mean an individual or Legal Entity
- exercising permissions granted by this License.
-
- "Source" form shall mean the preferred form for making modifications,
- including but not limited to software source code, documentation
- source, and configuration files.
-
- "Object" form shall mean any form resulting from mechanical
- transformation or translation of a Source form, including but
- not limited to compiled object code, generated documentation,
- and conversions to other media types.
-
- "Work" shall mean the work of authorship, whether in Source or
- Object form, made available under the License, as indicated by a
- copyright notice that is included in or attached to the work
- (an example is provided in the Appendix below).
-
- "Derivative Works" shall mean any work, whether in Source or Object
- form, that is based on (or derived from) the Work and for which the
- editorial revisions, annotations, elaborations, or other modifications
- represent, as a whole, an original work of authorship. For the purposes
- of this License, Derivative Works shall not include works that remain
- separable from, or merely link (or bind by name) to the interfaces of,
- the Work and Derivative Works thereof.
-
- "Contribution" shall mean any work of authorship, including
- the original version of the Work and any modifications or additions
- to that Work or Derivative Works thereof, that is intentionally
- submitted to Licensor for inclusion in the Work by the copyright owner
- or by an individual or Legal Entity authorized to submit on behalf of
- the copyright owner. For the purposes of this definition, "submitted"
- means any form of electronic, verbal, or written communication sent
- to the Licensor or its representatives, including but not limited to
- communication on electronic mailing lists, source code control systems,
- and issue tracking systems that are managed by, or on behalf of, the
- Licensor for the purpose of discussing and improving the Work, but
- excluding communication that is conspicuously marked or otherwise
- designated in writing by the copyright owner as "Not a Contribution."
-
- "Contributor" shall mean Licensor and any individual or Legal Entity
- on behalf of whom a Contribution has been received by Licensor and
- subsequently incorporated within the Work.
-
- 2. Grant of Copyright License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- copyright license to reproduce, prepare Derivative Works of,
- publicly display, publicly perform, sublicense, and distribute the
- Work and such Derivative Works in Source or Object form.
-
- 3. Grant of Patent License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- (except as stated in this section) patent license to make, have made,
- use, offer to sell, sell, import, and otherwise transfer the Work,
- where such license applies only to those patent claims licensable
- by such Contributor that are necessarily infringed by their
- Contribution(s) alone or by combination of their Contribution(s)
- with the Work to which such Contribution(s) was submitted. If You
- institute patent litigation against any entity (including a
- cross-claim or counterclaim in a lawsuit) alleging that the Work
- or a Contribution incorporated within the Work constitutes direct
- or contributory patent infringement, then any patent licenses
- granted to You under this License for that Work shall terminate
- as of the date such litigation is filed.
-
- 4. Redistribution. You may reproduce and distribute copies of the
- Work or Derivative Works thereof in any medium, with or without
- modifications, and in Source or Object form, provided that You
- meet the following conditions:
-
- (a) You must give any other recipients of the Work or
- Derivative Works a copy of this License; and
-
- (b) You must cause any modified files to carry prominent notices
- stating that You changed the files; and
-
- (c) You must retain, in the Source form of any Derivative Works
- that You distribute, all copyright, patent, trademark, and
- attribution notices from the Source form of the Work,
- excluding those notices that do not pertain to any part of
- the Derivative Works; and
-
- (d) If the Work includes a "NOTICE" text file as part of its
- distribution, then any Derivative Works that You distribute must
- include a readable copy of the attribution notices contained
- within such NOTICE file, excluding those notices that do not
- pertain to any part of the Derivative Works, in at least one
- of the following places: within a NOTICE text file distributed
- as part of the Derivative Works; within the Source form or
- documentation, if provided along with the Derivative Works; or,
- within a display generated by the Derivative Works, if and
- wherever such third-party notices normally appear. The contents
- of the NOTICE file are for informational purposes only and
- do not modify the License. You may add Your own attribution
- notices within Derivative Works that You distribute, alongside
- or as an addendum to the NOTICE text from the Work, provided
- that such additional attribution notices cannot be construed
- as modifying the License.
-
- You may add Your own copyright statement to Your modifications and
- may provide additional or different license terms and conditions
- for use, reproduction, or distribution of Your modifications, or
- for any such Derivative Works as a whole, provided Your use,
- reproduction, and distribution of the Work otherwise complies with
- the conditions stated in this License.
-
- 5. Submission of Contributions. Unless You explicitly state otherwise,
- any Contribution intentionally submitted for inclusion in the Work
- by You to the Licensor shall be under the terms and conditions of
- this License, without any additional terms or conditions.
- Notwithstanding the above, nothing herein shall supersede or modify
- the terms of any separate license agreement you may have executed
- with Licensor regarding such Contributions.
-
- 6. Trademarks. This License does not grant permission to use the trade
- names, trademarks, service marks, or product names of the Licensor,
- except as required for reasonable and customary use in describing the
- origin of the Work and reproducing the content of the NOTICE file.
-
- 7. Disclaimer of Warranty. Unless required by applicable law or
- agreed to in writing, Licensor provides the Work (and each
- Contributor provides its Contributions) on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- implied, including, without limitation, any warranties or conditions
- of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
- PARTICULAR PURPOSE. You are solely responsible for determining the
- appropriateness of using or redistributing the Work and assume any
- risks associated with Your exercise of permissions under this License.
-
- 8. Limitation of Liability. In no event and under no legal theory,
- whether in tort (including negligence), contract, or otherwise,
- unless required by applicable law (such as deliberate and grossly
- negligent acts) or agreed to in writing, shall any Contributor be
- liable to You for damages, including any direct, indirect, special,
- incidental, or consequential damages of any character arising as a
- result of this License or out of the use or inability to use the
- Work (including but not limited to damages for loss of goodwill,
- work stoppage, computer failure or malfunction, or any and all
- other commercial damages or losses), even if such Contributor
- has been advised of the possibility of such damages.
-
- 9. Accepting Warranty or Additional Liability. While redistributing
- the Work or Derivative Works thereof, You may choose to offer,
- and charge a fee for, acceptance of support, warranty, indemnity,
- or other liability obligations and/or rights consistent with this
- License. However, in accepting such obligations, You may act only
- on Your own behalf and on Your sole responsibility, not on behalf
- of any other Contributor, and only if You agree to indemnify,
- defend, and hold each Contributor harmless for any liability
- incurred by, or claims asserted against, such Contributor by reason
- of your accepting any such warranty or additional liability.
-
- END OF TERMS AND CONDITIONS
-
- APPENDIX: How to apply the Apache License to your work.
-
- To apply the Apache License to your work, attach the following
- boilerplate notice, with the fields enclosed by brackets "[]"
- replaced with your own identifying information. (Don't include
- the brackets!) The text should be enclosed in the appropriate
- comment syntax for the file format. We also recommend that a
- file or class name and description of purpose be included on the
- same "printed page" as the copyright notice for easier
- identification within third-party archives.
-
- Copyright [yyyy] [name of copyright owner]
-
- 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.
diff --git a/secret-sdk-proto/Cargo.toml b/secret-sdk-proto/Cargo.toml
index 67fd4ce..4cf5e47 100644
--- a/secret-sdk-proto/Cargo.toml
+++ b/secret-sdk-proto/Cargo.toml
@@ -2,7 +2,7 @@
name = "secret-sdk-proto"
version = "0.1.0"
authors = ["Kent"]
-license = "Apache-2.0"
+license = "Unlicense"
repository = "https://github.com/kent-3/secret-rust/tree/main/secret-sdk-proto"
description = "Protobuf struct definitions for interacting with Secret"
readme = "README.md"
diff --git a/secret-sdk-proto/README.md b/secret-sdk-proto/README.md
index e6f502a..68c9980 100644
--- a/secret-sdk-proto/README.md
+++ b/secret-sdk-proto/README.md
@@ -3,7 +3,7 @@
[![Crate][crate-image]][crate-link]
[![Docs][docs-image]][docs-link]
[![Build Status][build-image]][build-link]
-[![Apache 2.0 Licensed][license-image]][license-link]
+[![License][license-image]][license-link]
![MSRV][rustc-image]
Rust crate for interacting with [Protobufs] defined by [Secret Network].
@@ -23,8 +23,8 @@ This crate is supported on Rust **1.72** or newer.
[docs-link]: https://docs.rs/secret-sdk-proto/
[build-image]: https://github.com/kent-3/secret-rust/workflows/secret-sdk-proto/badge.svg
[build-link]: https://github.com/kent-3/secret-rust/actions/workflows/secret-sdk-proto.yml
-[license-image]: https://img.shields.io/badge/license-Apache2.0-blue.svg
-[license-link]: https://github.com/kent-3/secret-rust/blob/master/LICENSE
+[license-image]: https://img.shields.io/badge/license-Unlicense-blue.svg
+[license-link]: https://github.com/kent-3/secret-rust/blob/master/UNLICENSE
[rustc-image]: https://img.shields.io/badge/rustc-1.72+-blue.svg
[//]: # "links"
[Protobufs]: https://github.com/scrtlabs/SecretNetwork/tree/master/proto/secret
diff --git a/secret-utils/Cargo.toml b/secret-utils/Cargo.toml
index 3e5904b..b3f2bff 100644
--- a/secret-utils/Cargo.toml
+++ b/secret-utils/Cargo.toml
@@ -1,6 +1,11 @@
[package]
name = "secret-utils"
-version = "0.1.0"
+version = "0.0.0"
+authors = ["Kent"]
+license = "Unlicense"
+repository = "https://github.com/kent-3/secret-rust/tree/main/secret-utils"
+# description = ""
+readme = "README.md"
edition = "2021"
[dependencies]
diff --git a/secretrs/Cargo.toml b/secretrs/Cargo.toml
index 34d1f59..b48f54c 100644
--- a/secretrs/Cargo.toml
+++ b/secretrs/Cargo.toml
@@ -1,16 +1,20 @@
[package]
name = "secretrs"
-version = "0.0.1"
+version = "0.0.0"
authors = ["Kent"]
-license = "Apache-2.0"
+license = "Unlicense"
repository = "https://github.com/kent-3/secret-rust/tree/main/secretrs"
-description = ""
+description = "An extension of `cosmrs` for Secret."
readme = "README.md"
categories = ["cryptography", "cryptography::cryptocurrencies"]
keywords = ["blockchain", "cosmos"]
edition = "2021"
rust-version = "1.72"
+[[example]]
+name = "encrypt"
+path = "examples/encrypt.rs"
+
[[example]]
name = "query"
path = "examples/query.rs"
@@ -22,9 +26,30 @@ path = "examples/contract_query.rs"
required-features = ["grpc"]
[dependencies]
+
+# blockchain
cosmrs = { version = "0.16.0" }
secret-sdk-proto = { version = "0.1.0", default-features = false, path = "../secret-sdk-proto" }
-secret-utils = { path = "../secret-utils" }
+cosmwasm-std = { version = "=1.1.11", package = "secret-cosmwasm-std" }
+bip32 = "0.5.1"
+bip39 = "2.0.0"
+
+# general
+async-trait = "0.1.80"
+serde = "1.0.198"
+serde_json = "1.0.116"
+nanorand = { version = "0.7.0", features = ["getrandom", "zeroize"] }
+
+# crypto
+base64 = "0.22.0"
+hex = "0.4.3"
+hkdf = "0.12.4"
+sha2 = "0.10.8"
+aes-siv = "0.7.0"
+x25519-dalek = { version = "2.0.1", features = ["static_secrets"] }
+
+# errors
+thiserror = "1.0.51"
[features]
default = ["bip32"]
@@ -52,3 +77,7 @@ tonic-web-wasm-client = "0.5.1"
[target.'cfg(not(target_arch = "wasm32"))'.dev-dependencies]
tokio = { version = "1.37", features = ["rt", "sync", "time", "macros"] }
tonic = { version = "0.11.0", features = ["tls", "tls-webpki-roots", "transport"] }
+
+[package.metadata.docs.rs]
+all-features = true
+rustdoc-args = ["--cfg", "docsrs"]
diff --git a/secretrs/README.md b/secretrs/README.md
index b084160..e4dc6ed 100644
--- a/secretrs/README.md
+++ b/secretrs/README.md
@@ -3,7 +3,7 @@
[![Crate][crate-image]][crate-link]
[![Docs][docs-image]][docs-link]
[![Build Status][build-image]][build-link]
-[![Apache 2.0 Licensed][license-image]][license-link]
+[![License][license-image]][license-link]
![MSRV][rustc-image]
## Examples
@@ -24,6 +24,6 @@ This crate is supported on Rust **1.72** or newer.
[docs-link]: https://docs.rs/secretrs/
[build-image]: https://github.com/kent-3/secret-rust/workflows/secretrs/badge.svg
[build-link]: https://github.com/kent-3/secret-rust/actions/workflows/secretrs.yml
-[license-image]: https://img.shields.io/badge/license-Apache2.0-blue.svg
-[license-link]: https://github.com/kent-3/secret-rust/blob/master/LICENSE
+[license-image]: https://img.shields.io/badge/license-Unlicense-blue.svg
+[license-link]: https://github.com/kent-3/secret-rust/blob/master/UNLICENSE
[rustc-image]: https://img.shields.io/badge/rustc-1.72+-blue.svg
diff --git a/secretrs/examples/contract_query.rs b/secretrs/examples/contract_query.rs
index fbe06e4..2f62c76 100644
--- a/secretrs/examples/contract_query.rs
+++ b/secretrs/examples/contract_query.rs
@@ -46,7 +46,7 @@ async fn main() -> Result<()> {
// Encryption Utils section
- let account = secret_utils::Account::random();
+ let account = secretrs::utils::Account::random();
let (nonce, encrypted) = encrypt_msg(&query, &code_hash, &account, &enclave_key).await?;
let decrypter = decrypter(&nonce, &account, &enclave_key).await?;
@@ -84,9 +84,9 @@ async fn main() -> Result<()> {
let encrypted_bytes = BASE64_STANDARD.decode(&caps[1])?;
let decrypted_bytes = decrypter.decrypt(&encrypted_bytes)?;
let decrypted_string = String::from_utf8(decrypted_bytes)?;
- Err(secret_utils::Error::Generic(decrypted_string))
+ Err(secretrs::utils::Error::Generic(decrypted_string))
} else {
- Err(secret_utils::Error::Generic(error_message.to_string()))
+ Err(secretrs::utils::Error::Generic(error_message.to_string()))
}
}
}?;
diff --git a/secretrs/examples/encrypt.rs b/secretrs/examples/encrypt.rs
new file mode 100644
index 0000000..140ab6e
--- /dev/null
+++ b/secretrs/examples/encrypt.rs
@@ -0,0 +1,30 @@
+use color_eyre::Result;
+use serde::{Deserialize, Serialize};
+
+const CODE_HASH: &str = "9a00ca4ad505e9be7e6e6dddf8d939b7ec7e9ac8e109c8681f10db9cacb36d42";
+const TESTNET_ENCLAVE_KEY: &str =
+ "e24a22b31e3d34e0e00bcd32189548f1ccbdc9cda8f5a266219b908582b6f03f";
+
+#[derive(Serialize, Deserialize)]
+#[serde(rename_all = "snake_case")]
+pub enum QueryMsg {
+ TokenInfo {},
+}
+
+#[tokio::main(flavor = "current_thread")]
+async fn main() -> Result<()> {
+ let query = QueryMsg::TokenInfo {};
+ let account = secretrs::utils::Account::random();
+
+ let (_nonce, encrypted) =
+ secretrs::utils::encrypt_msg(&query, CODE_HASH, &account, TESTNET_ENCLAVE_KEY).await?;
+
+ println!("{}", hex::encode(&encrypted));
+
+ // Use this to decrypt responses from the enclave:
+ //
+ // let decrypter = secret_utils::decrypter(&nonce, &account, TESTNET_ENCLAVE_KEY).await?;
+ // let decrypted_bytes = decrypter.decrypt(&response.data)?;
+
+ Ok(())
+}
diff --git a/secretrs/src/lib.rs b/secretrs/src/lib.rs
index 6a96a20..58b8158 100644
--- a/secretrs/src/lib.rs
+++ b/secretrs/src/lib.rs
@@ -2,8 +2,7 @@ pub use cosmrs::*;
pub use secret_sdk_proto::{self as proto, SECRET_VERSION};
pub mod compute;
-
-pub use secret_utils as utils;
+pub mod utils;
#[cfg(feature = "grpc-core")]
pub use crate::tonic::{query_clients::*, service_clients::*};
diff --git a/secretrs/src/utils/account.rs b/secretrs/src/utils/account.rs
new file mode 100644
index 0000000..4dcbe37
--- /dev/null
+++ b/secretrs/src/utils/account.rs
@@ -0,0 +1,114 @@
+use cosmrs::{
+ crypto::{secp256k1::SigningKey, PublicKey},
+ AccountId,
+};
+use cosmwasm_std::Addr;
+
+use crate::utils::{
+ consts,
+ crypto::{self, Key},
+};
+
+#[derive(Clone)]
+pub struct Account {
+ prvk: bip32::XPrv,
+ pubk: PublicKey,
+}
+
+impl Account {
+ pub fn from_mnemonic(s: &str) -> Option {
+ let mnemonic = bip39::Mnemonic::parse(s).ok()?;
+ // empty passphrase
+ Some(Account::from_seed(mnemonic.to_seed("")))
+ }
+
+ pub fn from_seed(seed: [u8; 64]) -> Account {
+ let path = consts::SCRT_DERIVATION_PATH
+ .parse()
+ .expect("invalid scrt derivation path");
+ let prvk =
+ bip32::XPrv::derive_from_path(seed, &path).expect("private key derivation failed");
+ let pubk = SigningKey::from(&prvk).public_key();
+ Account { prvk, pubk }
+ }
+
+ pub fn random() -> Account {
+ use nanorand::rand::Rng;
+ let mut seed = [0; 64];
+ let mut rng = nanorand::rand::ChaCha8::new();
+ rng.fill_bytes(&mut seed);
+
+ let path = consts::SCRT_DERIVATION_PATH
+ .parse()
+ .expect("invalid scrt derivation path");
+ let prvk =
+ bip32::XPrv::derive_from_path(seed, &path).expect("private key derivation failed");
+ let pubk = SigningKey::from(&prvk).public_key();
+ Account { prvk, pubk }
+ }
+
+ pub fn addr(&self) -> Addr {
+ Addr::unchecked(self.id().as_ref())
+ }
+
+ #[allow(unused)]
+ pub(crate) fn signing_key(&self) -> SigningKey {
+ SigningKey::from(&self.prvk)
+ }
+
+ pub(crate) fn id(&self) -> AccountId {
+ self.pubk
+ .account_id(consts::CHAIN_PREFIX)
+ .expect("invalid public key type")
+ }
+
+ pub(crate) fn prv_pub_bytes(&self) -> (Key, Key) {
+ crypto::edd25519_keys(&self.prvk)
+ }
+}
+
+pub fn a() -> Account {
+ Account::from_mnemonic(A_MNEMONIC).unwrap()
+}
+
+pub fn b() -> Account {
+ Account::from_mnemonic(B_MNEMONIC).unwrap()
+}
+
+pub fn c() -> Account {
+ Account::from_mnemonic(C_MNEMONIC).unwrap()
+}
+
+pub fn d() -> Account {
+ Account::from_mnemonic(D_MNEMONIC).unwrap()
+}
+
+#[cfg(test)]
+mod test {
+ use super::*;
+
+ #[test]
+ fn accounts_from_mnemonic() {
+ assert_eq!(
+ a().addr(),
+ Addr::unchecked("secret1ap26qrlp8mcq2pg6r47w43l0y8zkqm8a450s03")
+ );
+ assert_eq!(
+ b().addr(),
+ Addr::unchecked("secret1fc3fzy78ttp0lwuujw7e52rhspxn8uj52zfyne")
+ );
+ assert_eq!(
+ c().addr(),
+ Addr::unchecked("secret1ajz54hz8azwuy34qwy9fkjnfcrvf0dzswy0lqq")
+ );
+ assert_eq!(
+ d().addr(),
+ Addr::unchecked("secret1ldjxljw7v4vk6zhyduywh04hpj0jdwxsmrlatf")
+ );
+ }
+}
+
+static A_MNEMONIC: &str = "grant rice replace explain federal release fix clever romance raise often wild taxi quarter soccer fiber love must tape steak together observe swap guitar";
+static B_MNEMONIC: &str = "jelly shadow frog dirt dragon use armed praise universe win jungle close inmate rain oil canvas beauty pioneer chef soccer icon dizzy thunder meadow";
+static C_MNEMONIC: &str = "chair love bleak wonder skirt permit say assist aunt credit roast size obtain minute throw sand usual age smart exact enough room shadow charge";
+static D_MNEMONIC: &str = "word twist toast cloth movie predict advance crumble escape whale sail such angry muffin balcony keen move employ cook valve hurt glimpse breeze brick";
diff --git a/secretrs/src/utils/consts.rs b/secretrs/src/utils/consts.rs
new file mode 100644
index 0000000..fe21295
--- /dev/null
+++ b/secretrs/src/utils/consts.rs
@@ -0,0 +1,11 @@
+#![allow(unused)]
+
+// Chain info
+pub static CHAIN_PREFIX: &str = "secret";
+pub static SCRT_DERIVATION_PATH: &str = "m/44'/529'/0'/0/0";
+pub static COIN_DENOM: &str = "uscrt";
+
+// Host info
+pub static TESTNET_HOST: &str = "http://rpc.testnet.secretsaturn.net";
+pub static TESTNET_ENCLAVE_KEY: &str =
+ "e24a22b31e3d34e0e00bcd32189548f1ccbdc9cda8f5a266219b908582b6f03f";
diff --git a/secretrs/src/utils/crypto/cert.rs b/secretrs/src/utils/crypto/cert.rs
new file mode 100644
index 0000000..9685820
--- /dev/null
+++ b/secretrs/src/utils/crypto/cert.rs
@@ -0,0 +1,68 @@
+#![allow(unused)]
+
+use super::Key;
+use base64::prelude::{Engine, BASE64_STANDARD};
+
+#[derive(Debug, thiserror::Error)]
+pub enum MalformedError {
+ #[error("The DER byte buffer is too short")]
+ IncorrectLength,
+ #[error("The Netscape Comment is invalid utf8: {0}")]
+ Utf8(#[from] std::str::Utf8Error),
+ #[error("The Netscape Comment has invalid base64 encoding: {0}")]
+ Base64(#[from] base64::DecodeError),
+}
+
+// https://github.com/scrtlabs/SecretNetwork/blob/19bbd80307b4d6b49f04ad5c62008a3f25ba3f1e/cosmwasm/enclaves/execute/src/registration/cert.rs#L213
+fn extract_asn1_value<'a>(cert: &'a [u8], oid: &[u8]) -> Result<&'a [u8], MalformedError> {
+ let mut offset = cert
+ .windows(oid.len())
+ .position(|window| window == oid)
+ .ok_or(MalformedError::IncorrectLength)?;
+
+ offset += 12; // 11 + TAG (0x04)
+
+ if offset + 2 >= cert.len() {
+ return Err(MalformedError::IncorrectLength);
+ }
+
+ // Obtain Netscape Comment length
+ let mut len = cert[offset] as usize;
+ if len > 0x80 {
+ len = (cert[offset + 1] as usize) * 0x100 + (cert[offset + 2] as usize);
+ offset += 2;
+ }
+
+ // Obtain Netscape Comment
+ offset += 1;
+
+ if offset + len >= cert.len() {
+ return Err(MalformedError::IncorrectLength);
+ }
+
+ Ok(&cert[offset..offset + len])
+}
+
+fn extract_netscape_comment(cert_der: &[u8]) -> Result<&[u8], MalformedError> {
+ // Search for Netscape Comment OID
+ let ns_cmt_oid = &[
+ 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x86, 0xF8, 0x42, 0x01, 0x0D,
+ ];
+ extract_asn1_value(cert_der, ns_cmt_oid)
+}
+
+pub(crate) fn consensus_io_pubk(cert_der: &[u8]) -> Result {
+ // localsecret used software SGX so we can just deserialise the payload:
+ // https://github.com/scrtlabs/SecretNetwork/blob/19bbd80307b4d6b49f04ad5c62008a3f25ba3f1e/x/registration/remote_attestation/remote_attestation.go#L25
+ let buf = extract_netscape_comment(cert_der)?;
+ let b64 = std::str::from_utf8(buf)?;
+ let pubk = BASE64_STANDARD.decode(b64)?;
+
+ if pubk.len() < super::KEY_LEN {
+ return Err(MalformedError::IncorrectLength);
+ }
+
+ let pubk = super::clone_into_key(&pubk);
+
+ Ok(pubk)
+}
diff --git a/secretrs/src/utils/crypto/mod.rs b/secretrs/src/utils/crypto/mod.rs
new file mode 100644
index 0000000..7a74c6b
--- /dev/null
+++ b/secretrs/src/utils/crypto/mod.rs
@@ -0,0 +1,173 @@
+use aes_siv::{siv::Aes128Siv as Siv, Key as SivKey, KeyInit};
+
+pub mod cert;
+
+const KEY_LEN: usize = 256 / 8; // 32 bytes
+const NONCE_LEN: usize = 32;
+
+pub type Nonce = [u8; NONCE_LEN];
+pub type Key = [u8; KEY_LEN];
+
+#[derive(Debug, thiserror::Error)]
+pub enum CryptoError {
+ #[error("Incorrect key length, expected 32 byte key")]
+ IncorrectKeyLength,
+ #[error("Encryption failed")]
+ Encrypt,
+ #[error("Decryption failed")]
+ Decrypt,
+}
+
+pub fn edd25519_keys(secret: &bip32::XPrv) -> (Key, Key) {
+ let secret = clone_into_key(&secret.private_key().to_bytes());
+ let secret = x25519_dalek::StaticSecret::from(secret);
+ let public = x25519_dalek::PublicKey::from(&secret);
+ (secret.to_bytes(), public.to_bytes())
+}
+
+pub fn encrypt(
+ secret: &Key,
+ public: &Key,
+ peer: &Key,
+ plaintext: &[u8],
+) -> Result<(Nonce, Vec), CryptoError> {
+ let nonce = generate_nonce();
+
+ let shared_secret = encryption_key(secret, peer, &nonce)?;
+
+ let mut cipher = Siv::new(&SivKey::::from(shared_secret));
+
+ let ciphertext = cipher
+ .encrypt([[]], plaintext)
+ .map_err(|_| CryptoError::Encrypt)?;
+
+ let ciphertext = [nonce.as_slice(), public.as_slice(), &ciphertext].concat();
+
+ Ok((nonce, ciphertext))
+}
+
+pub fn decrypt(
+ secret: &Key,
+ peer: &Key,
+ nonce: &Nonce,
+ ciphertext: &[u8],
+) -> Result, CryptoError> {
+ let shared_secret = encryption_key(secret, peer, nonce)?;
+
+ let mut cipher = Siv::new(&SivKey::::from(shared_secret));
+
+ let plaintext = cipher
+ .decrypt([[]], ciphertext)
+ .map_err(|_| CryptoError::Decrypt)?;
+
+ Ok(plaintext)
+}
+
+#[derive(Debug, Clone, Copy)]
+pub struct Decrypter {
+ secret: Key,
+ peer: Key,
+ nonce: Nonce,
+}
+
+impl Decrypter {
+ pub fn new(secret: Key, peer: Key, nonce: Nonce) -> Self {
+ Decrypter {
+ secret,
+ peer,
+ nonce,
+ }
+ }
+
+ pub fn decrypt(&self, ciphertext: &[u8]) -> Result, CryptoError> {
+ decrypt(&self.secret, &self.peer, &self.nonce, ciphertext)
+ }
+}
+
+fn generate_nonce() -> Nonce {
+ use nanorand::rand::Rng;
+ let mut nonce = [0; NONCE_LEN];
+ let mut rng = nanorand::rand::ChaCha8::new();
+ rng.fill_bytes(&mut nonce);
+ nonce
+}
+
+fn encryption_key(secret: &Key, public: &Key, nonce: &Nonce) -> Result {
+ let secret = x25519_dalek::StaticSecret::from(*secret);
+ let public = x25519_dalek::PublicKey::from(*public);
+ let shared = secret.diffie_hellman(&public);
+
+ let ikm = &[shared.as_bytes(), nonce.as_slice()].concat();
+
+ let mut key = [0u8; KEY_LEN];
+ hkdf::Hkdf::::new(Some(&HKDF_SALT), ikm)
+ .expand(&[], &mut key)
+ .map_err(|_| CryptoError::IncorrectKeyLength)?;
+
+ Ok(key)
+}
+
+// TODO - this could panic. impl TryFrom or something
+pub fn clone_into_key(slice: &[u8]) -> Key {
+ let mut key = Default::default();
+ Key::as_mut(&mut key).clone_from_slice(slice);
+ key
+}
+
+static HKDF_SALT: [u8; 32] = [
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x4b, 0xea, 0xd8, 0xdf, 0x69, 0x99,
+ 0x08, 0x52, 0xc2, 0x02, 0xdb, 0x0e, 0x00, 0x97, 0xc1, 0xa1, 0x2e, 0xa6, 0x37, 0xd7, 0xe9, 0x6d,
+];
+
+#[cfg(test)]
+mod test {
+ use crate::utils::account::Account;
+
+ use super::*;
+
+ fn gen_seed() -> [u8; 64] {
+ use nanorand::rand::Rng;
+ let mut seed = [0; 64];
+ let mut rng = nanorand::rand::ChaCha8::new();
+ rng.fill_bytes(&mut seed);
+ seed
+ }
+
+ fn gen_keypair() -> (Key, Key) {
+ let acc = Account::from_seed(gen_seed());
+ acc.prv_pub_bytes()
+ }
+
+ fn gen_bip32_key() -> bip32::XPrv {
+ bip32::XPrv::new(gen_seed()).unwrap()
+ }
+
+ #[test]
+ fn x25519_works() {
+ let my_key = gen_bip32_key();
+ let peer_key = gen_bip32_key();
+
+ let my_priv = clone_into_key(&my_key.private_key().to_bytes());
+ let my_priv = x25519_dalek::StaticSecret::from(my_priv);
+ let my_pub = x25519_dalek::PublicKey::from(&my_priv);
+
+ let peer_priv = clone_into_key(&peer_key.private_key().to_bytes());
+ let peer_priv = x25519_dalek::StaticSecret::from(peer_priv);
+ let peer_pub = x25519_dalek::PublicKey::from(&peer_priv);
+
+ let my_shared = my_priv.diffie_hellman(&peer_pub);
+ let peer_shared = peer_priv.diffie_hellman(&my_pub);
+
+ assert_eq!(my_shared.to_bytes(), peer_shared.to_bytes());
+ }
+
+ #[test]
+ fn shared_encryption_key() {
+ let (my_priv, my_pub) = gen_keypair();
+ let (peer_priv, peer_pub) = gen_keypair();
+ let nonce = generate_nonce();
+ let my_shared_key = encryption_key(&my_priv, &peer_pub, &nonce).unwrap();
+ let peer_shared_key = encryption_key(&peer_priv, &my_pub, &nonce).unwrap();
+ assert_eq!(my_shared_key, peer_shared_key)
+ }
+}
diff --git a/secretrs/src/utils/error.rs b/secretrs/src/utils/error.rs
new file mode 100644
index 0000000..a40fb45
--- /dev/null
+++ b/secretrs/src/utils/error.rs
@@ -0,0 +1,45 @@
+pub type Result = std::result::Result;
+
+pub use crate::utils::crypto::cert::MalformedError;
+pub use crate::utils::crypto::CryptoError;
+pub use crate::utils::types::ParseError;
+
+#[derive(Debug, thiserror::Error)]
+pub enum Error {
+ #[error("{0}")]
+ Generic(String),
+ #[error("Failed to read contract file: {0} - {1}")]
+ ContractFile(String, std::io::Error),
+ #[error("Contract with label {0} already deployed")]
+ ContractLabelExists(String),
+ #[error("Contract Info not found for code id: {0}")]
+ ContractInfoNotFound(crate::utils::CodeId),
+ #[error("Timed out waiting for first block after {0} seconds")]
+ FirstBlockTimeout(u128),
+ #[error("ABCI Query failed: {0}")]
+ AbciQuery(String),
+ #[error("CosmWasm Error: {0}")]
+ CosmWasm(#[from] cosmwasm_std::StdError),
+ #[error("Account {0} not found")]
+ AccountNotFound(cosmwasm_std::Addr),
+ #[error("CosmRs error: {0}")]
+ CosmRs(#[from] cosmrs::ErrorReport),
+ #[error("Broadcast error - check tx failed: {0}")]
+ BroadcastTxCheck(String),
+ #[error("Broadcast error - deliver tx failed: {0}")]
+ BroadcastTxDeliver(String),
+ #[error("Failed to parse message response: {0}")]
+ ParseMsgResponse(#[from] ParseError),
+ #[error("Parsing TEE cert failed: {0}")]
+ ParseTEECert(#[from] MalformedError),
+ #[error("Cryptographic error: {0}")]
+ Crypto(#[from] CryptoError),
+ #[error("Failed to deserialise JSON response: {0}")]
+ Json(#[from] serde_json::Error),
+ #[error("Failed to decode Base64 response: {0}")]
+ Base64(#[from] base64::DecodeError),
+ #[error(transparent)]
+ Utf8(#[from] std::string::FromUtf8Error),
+ #[error(transparent)]
+ ParseHex(#[from] hex::FromHexError),
+}
diff --git a/secretrs/src/utils/mod.rs b/secretrs/src/utils/mod.rs
new file mode 100644
index 0000000..94a8f7f
--- /dev/null
+++ b/secretrs/src/utils/mod.rs
@@ -0,0 +1,64 @@
+pub mod account;
+pub(crate) mod consts;
+pub(crate) mod crypto;
+pub mod error;
+pub mod types;
+
+pub use crate::utils::error::Error;
+pub use account::Account;
+pub use types::{CodeHash, CodeId, Contract, TxResponse};
+
+use crate::utils::error::Result;
+use crypto::{Decrypter, Nonce};
+use std::str::FromStr;
+
+// IDEA - for a nice API, take as input only a code_hash, enclave_public_key, and some entropy.
+// do a sha256 on the entropy to get a [u8;32] to use as the prv_key. generate a pub_key.
+// return a struct that has methods for encrypt and decrypt
+//
+// let enigma = secretrs::Enigma::new(code_hash, enclave_public_key, entropy);
+// let encrypted = enigma.encrypt(msg);
+//
+// OR
+//
+// let (encrypter, decrypter) = secretrs::Enigma::new(code_hash, enclave_public_key, entropy);
+// let encrypted = encrypter.encrypt(msg);
+
+// TODO - instead of `Account`, accept a key / seed [u8; 32]
+// For queries, the specific keys don't matter, so it doesn't make sense to require `Account`
+// as input. You only need to provide a private key / seed, and it returns a prv_pub pair.
+pub async fn encrypt_msg(
+ msg: &M,
+ code_hash: &str,
+ account: &Account,
+ enclave_public_key: &str,
+) -> Result<(Nonce, Vec)> {
+ let code_hash = CodeHash::from_str(code_hash)?;
+
+ let enclave_key = crypto::clone_into_key(&hex::decode(enclave_public_key)?);
+ let msg = serde_json::to_vec(msg).expect("msg cannot be serialized as JSON");
+ let plaintext = [code_hash.to_hex_string().as_bytes(), msg.as_slice()].concat();
+ encrypt_msg_raw(&plaintext, account, enclave_key).await
+}
+
+async fn encrypt_msg_raw(
+ msg: &[u8],
+ account: &Account,
+ enclave_public_key: crypto::Key,
+) -> Result<(Nonce, Vec)> {
+ let (prvk, pubk) = account.prv_pub_bytes();
+ let io_key = enclave_public_key;
+ let nonce_ciphertext = crypto::encrypt(&prvk, &pubk, &io_key, msg)?;
+ Ok(nonce_ciphertext)
+}
+
+pub async fn decrypter(
+ nonce: &Nonce,
+ account: &Account,
+ enclave_public_key: &str,
+) -> Result {
+ let (secret, _) = account.prv_pub_bytes();
+ let enclave_key = crypto::clone_into_key(&hex::decode(enclave_public_key)?);
+ let io_key = enclave_key;
+ Ok(Decrypter::new(secret, io_key, *nonce))
+}
diff --git a/secretrs/src/utils/types.rs b/secretrs/src/utils/types.rs
new file mode 100644
index 0000000..736b79c
--- /dev/null
+++ b/secretrs/src/utils/types.rs
@@ -0,0 +1,219 @@
+#![allow(unused)]
+
+use std::{collections::HashMap, str::FromStr};
+
+use cosmrs::AccountId;
+
+use crate::utils::consts::CHAIN_PREFIX;
+
+#[derive(Debug, thiserror::Error)]
+pub enum ParseError {
+ #[error("Failed to parse code id: {0}")]
+ CodeId(#[from] ParseCodeIdError),
+ #[error("Failed to parse code hash: {0}")]
+ CodeHash(#[from] hex::FromHexError),
+ #[error("Failed to parse contract address: {0}")]
+ ContractAddress(#[from] cosmrs::ErrorReport),
+ #[error("Failed to parse contract initialisation: {0}")]
+ ContractInit(#[from] ParseContractInitError),
+}
+
+#[derive(Debug, Clone, Copy)]
+pub struct CodeId(u64);
+
+impl std::fmt::Display for CodeId {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ write!(f, "{}", self.0)
+ }
+}
+
+impl From for u64 {
+ fn from(ci: CodeId) -> Self {
+ ci.0
+ }
+}
+
+#[derive(Debug, thiserror::Error)]
+pub enum ParseCodeIdError {
+ #[error(transparent)]
+ Utf8(#[from] std::str::Utf8Error),
+ #[error(transparent)]
+ ParseInt(#[from] std::num::ParseIntError),
+}
+
+impl TryFrom> for CodeId {
+ type Error = ParseError;
+
+ fn try_from(value: Vec) -> Result {
+ fn parse(value: &[u8]) -> Result {
+ let s = std::str::from_utf8(value)?;
+ let code_id = s.parse()?;
+ Ok(CodeId(code_id))
+ }
+ parse(&value).map_err(Self::Error::from)
+ }
+}
+
+#[derive(Debug, Clone)]
+pub(crate) struct ContractInit(AccountId);
+
+impl ContractInit {
+ pub fn into_contract(self, code_hash: CodeHash) -> Contract {
+ Contract {
+ id: self.0,
+ code_hash,
+ }
+ }
+}
+
+#[derive(Debug, thiserror::Error)]
+pub enum ParseContractInitError {
+ #[error("Failed to parse address bytes: {0}")]
+ Address(#[from] cosmrs::ErrorReport),
+}
+
+impl TryFrom> for ContractInit {
+ type Error = ParseError;
+
+ fn try_from(value: Vec) -> Result {
+ fn parse(value: &[u8]) -> Result {
+ let id = AccountId::new(CHAIN_PREFIX, value)?;
+ Ok(ContractInit(id))
+ }
+ parse(&value).map_err(Self::Error::from)
+ }
+}
+
+#[derive(Debug, Clone)]
+pub struct Contract {
+ id: AccountId,
+ code_hash: CodeHash,
+}
+
+impl Contract {
+ pub fn try_from_address_with_code_hash(
+ address: &str,
+ code_hash: &str,
+ ) -> Result {
+ let id = AccountId::from_str(address)?;
+ let code_hash = CodeHash::from_str(code_hash)?;
+ Ok(Contract { id, code_hash })
+ }
+ pub fn addr(&self) -> cosmwasm_std::Addr {
+ cosmwasm_std::Addr::unchecked(self.id.as_ref())
+ }
+
+ pub fn code_hash_string(&self) -> String {
+ self.code_hash.to_hex_string()
+ }
+
+ pub(crate) fn id(&self) -> AccountId {
+ self.id.clone()
+ }
+
+ pub(crate) fn code_hash(&self) -> &CodeHash {
+ &self.code_hash
+ }
+}
+
+#[derive(Debug, Clone)]
+pub struct CodeHash(Vec);
+
+impl From> for CodeHash {
+ fn from(b: Vec) -> Self {
+ CodeHash(b)
+ }
+}
+
+impl FromStr for CodeHash {
+ type Err = ParseError;
+
+ fn from_str(s: &str) -> Result {
+ hex::decode(s).map(CodeHash).map_err(ParseError::from)
+ }
+}
+
+impl CodeHash {
+ pub fn as_bytes(&self) -> &[u8] {
+ self.0.as_slice()
+ }
+
+ pub fn to_hex_string(&self) -> String {
+ use core::fmt::Write;
+ let mut s = String::with_capacity(2 * self.0.len());
+ for byte in self.as_bytes() {
+ write!(s, "{:02X}", byte).expect("could not write byte as hex to string");
+ }
+ s
+ }
+}
+
+impl std::fmt::Display for CodeHash {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ write!(f, "{}", self.to_hex_string())
+ }
+}
+
+#[derive(Debug)]
+pub struct Event {
+ pub(crate) _type: String,
+ pub(crate) attrs: HashMap,
+}
+
+#[derive(Debug)]
+pub struct TxResponse {
+ pub response: Option,
+ pub gas_used: u64,
+ pub(crate) events: Vec,
+}
+
+impl TxResponse {
+ pub fn event_attr(&self, event_type: &str, attr: &str) -> Option<&str> {
+ self.events
+ .iter()
+ .find(|e| e._type == event_type)
+ .and_then(|e| e.attrs.get(attr))
+ .map(String::as_str)
+ }
+
+ /// panics if the response is `None`
+ pub fn into_inner(self) -> T {
+ self.response.unwrap()
+ }
+
+ pub(crate) fn map U>(self, f: F) -> TxResponse {
+ TxResponse {
+ response: self.response.map(f),
+ gas_used: self.gas_used,
+ events: self.events,
+ }
+ }
+
+ pub(crate) fn try_map(self, f: F) -> crate::utils::error::Result>
+ where
+ crate::utils::error::Error: From,
+ F: FnOnce(T) -> Result,
+ {
+ let response = self.response.map(f).transpose()?;
+ Ok(TxResponse {
+ response,
+ gas_used: self.gas_used,
+ events: self.events,
+ })
+ }
+}
+
+#[derive(Debug)]
+pub(crate) struct AccountInfo {
+ pub account_number: u64,
+ pub sequence_number: cosmrs::tx::SequenceNumber,
+}
+
+impl From for AccountInfo {
+ fn from(ba: cosmrs::proto::cosmos::auth::v1beta1::BaseAccount) -> Self {
+ AccountInfo {
+ account_number: ba.account_number,
+ sequence_number: ba.sequence,
+ }
+ }
+}