Compare commits
95 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 666ce5e368 | |||
| dbb65259ed | |||
| 38896e6959 | |||
| a56068e28a | |||
| 9a4293a5b9 | |||
| cdddb44099 | |||
| d309b44ad7 | |||
| 22539c3e7d | |||
| edde411568 | |||
| 75f2fb7039 | |||
| f768c8e8e2 | |||
| 200efebc37 | |||
| a429d6528e | |||
| ebed210de2 | |||
| d062524d32 | |||
| f1d3c33391 | |||
| 89eea3100e | |||
| d893c806c2 | |||
| 7846058802 | |||
| 42fbb6684d | |||
| f705884a53 | |||
| 2f55c031da | |||
| a9eb6052ff | |||
| 3bc7ced2cf | |||
| 8abcc58055 | |||
| 76ff03b248 | |||
| ccf3420aab | |||
| 5df76ea2a9 | |||
| 33992542b1 | |||
| a95ee3f334 | |||
| 0a92f04048 | |||
| 368b105e27 | |||
| 813cbda891 | |||
| a8af641ec4 | |||
| f41a2d3a99 | |||
| a3b7cb52c9 | |||
| 60846b57f6 | |||
| 8ed09d74b3 | |||
| cd52bc577c | |||
| ed021ff467 | |||
| 4f67998127 | |||
| d06a8e0b21 | |||
| 3f05c0d4b9 | |||
| 1a37e60483 | |||
| 19775cf917 | |||
| 0abc07c96f | |||
| fbfeacf539 | |||
| e1583daaa3 | |||
| e904627513 | |||
| 04664c8ae1 | |||
| 4da68438c0 | |||
| 05c1554109 | |||
| 2b83442a6d | |||
| f982cb49c2 | |||
| 0c05727e58 | |||
| 3c432ac073 | |||
| 52ffd2e798 | |||
| be8c7b4953 | |||
| 8e4bc12b87 | |||
| 4895820985 | |||
| 8500618fe9 | |||
| a5b390b98f | |||
| ff66674f61 | |||
| a7cf34e812 | |||
| a85dad6bd7 | |||
| 5b8a14f74b | |||
| 730c2efea6 | |||
| c9d6a8cc25 | |||
| 230b2b1784 | |||
| e4e9615535 | |||
| a19ee8f2aa | |||
| abfc68108a | |||
| 7bf1adff28 | |||
| ed90e358fb | |||
| c7d0e26946 | |||
| 8d65c25986 | |||
| a143d5f4f6 | |||
| c041d11673 | |||
| 82e82943aa | |||
| e4fd87be2c | |||
| 19ffe217f1 | |||
| 079bfa52e7 | |||
| be9a2c26e7 | |||
| d6f3eb6411 | |||
| 144f3bed9c | |||
| c1174e64d4 | |||
| 312ecbe4dc | |||
| d2afa587e4 | |||
| 224c4c1870 | |||
| 3f8abdb74f | |||
| 3baac1292d | |||
| dc88650d6d | |||
| 681c054890 | |||
| f623bbd57c | |||
| d4d576f363 |
@@ -1 +1,2 @@
|
||||
nym-validator-rewarder/.sqlx/** diff=nodiff
|
||||
nym-node-status-api/nym-node-status-api/.sqlx/** diff=nodiff
|
||||
|
||||
+149
-265
@@ -9,7 +9,7 @@
|
||||
"version": "1.0.0",
|
||||
"dependencies": {
|
||||
"@actions/core": "^1.10.1",
|
||||
"@actions/github": "^5.1.1",
|
||||
"@actions/github": "^6.0.0",
|
||||
"@octokit/auth-action": "^4.0.1",
|
||||
"@octokit/rest": "^20.0.2",
|
||||
"hasha": "^5.2.0",
|
||||
@@ -29,22 +29,34 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@actions/github": {
|
||||
"version": "5.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@actions/github/-/github-5.1.1.tgz",
|
||||
"integrity": "sha512-Nk59rMDoJaV+mHCOJPXuvB1zIbomlKS0dmSIqPGxd0enAXBnOfn4VWF+CGtRCwXZG9Epa54tZA7VIRlJDS8A6g==",
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@actions/github/-/github-6.0.0.tgz",
|
||||
"integrity": "sha512-alScpSVnYmjNEXboZjarjukQEzgCRmjMv6Xj47fsdnqGS73bjJNDpiiXmp8jr0UZLdUB6d9jW63IcmddUP+l0g==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@actions/http-client": "^2.0.1",
|
||||
"@octokit/core": "^3.6.0",
|
||||
"@octokit/plugin-paginate-rest": "^2.17.0",
|
||||
"@octokit/plugin-rest-endpoint-methods": "^5.13.0"
|
||||
"@actions/http-client": "^2.2.0",
|
||||
"@octokit/core": "^5.0.1",
|
||||
"@octokit/plugin-paginate-rest": "^9.0.0",
|
||||
"@octokit/plugin-rest-endpoint-methods": "^10.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@actions/http-client": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-2.1.1.tgz",
|
||||
"integrity": "sha512-qhrkRMB40bbbLo7gF+0vu+X+UawOvQQqNAA/5Unx774RS8poaOhThDOG6BGmxvAnxhQnDp2BG/ZUm65xZILTpw==",
|
||||
"version": "2.2.3",
|
||||
"resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-2.2.3.tgz",
|
||||
"integrity": "sha512-mx8hyJi/hjFvbPokCg4uRd4ZX78t+YyRPtnKWwIl+RzNaVuFpQHfmlGVfsKEJN8LwTCvL+DfVgAM04XaHkm6bA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"tunnel": "^0.0.6"
|
||||
"tunnel": "^0.0.6",
|
||||
"undici": "^5.25.4"
|
||||
}
|
||||
},
|
||||
"node_modules/@fastify/busboy": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.1.1.tgz",
|
||||
"integrity": "sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/auth-action": {
|
||||
@@ -59,14 +71,6 @@
|
||||
"node": ">= 18"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/auth-action/node_modules/@octokit/auth-token": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-4.0.0.tgz",
|
||||
"integrity": "sha512-tY/msAuJo6ARbK6SPIxZrPBms3xPbfwBrulZe0Wtr/DIY9lje2HeV1uoebShn6mx7SjCHif6EjMvoREj+gZ+SA==",
|
||||
"engines": {
|
||||
"node": ">= 18"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/auth-action/node_modules/@octokit/openapi-types": {
|
||||
"version": "20.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-20.0.0.tgz",
|
||||
@@ -81,115 +85,152 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/auth-token": {
|
||||
"version": "2.5.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-2.5.0.tgz",
|
||||
"integrity": "sha512-r5FVUJCOLl19AxiuZD2VRZ/ORjp/4IN98Of6YJoJOkY75CIBuYfmiNHGrDwXr+aLGG55igl9QrxX3hbiXlLb+g==",
|
||||
"dependencies": {
|
||||
"@octokit/types": "^6.0.3"
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-4.0.0.tgz",
|
||||
"integrity": "sha512-tY/msAuJo6ARbK6SPIxZrPBms3xPbfwBrulZe0Wtr/DIY9lje2HeV1uoebShn6mx7SjCHif6EjMvoREj+gZ+SA==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 18"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/core": {
|
||||
"version": "3.6.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/core/-/core-3.6.0.tgz",
|
||||
"integrity": "sha512-7RKRKuA4xTjMhY+eG3jthb3hlZCsOwg3rztWh75Xc+ShDWOfDDATWbeZpAHBNRpm4Tv9WgBMOy1zEJYXG6NJ7Q==",
|
||||
"version": "5.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/core/-/core-5.2.0.tgz",
|
||||
"integrity": "sha512-1LFfa/qnMQvEOAdzlQymH0ulepxbxnCYAKJZfMci/5XJyIHWgEYnDmgnKakbTh7CH2tFQ5O60oYDvns4i9RAIg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@octokit/auth-token": "^2.4.4",
|
||||
"@octokit/graphql": "^4.5.8",
|
||||
"@octokit/request": "^5.6.3",
|
||||
"@octokit/request-error": "^2.0.5",
|
||||
"@octokit/types": "^6.0.3",
|
||||
"@octokit/auth-token": "^4.0.0",
|
||||
"@octokit/graphql": "^7.1.0",
|
||||
"@octokit/request": "^8.3.1",
|
||||
"@octokit/request-error": "^5.1.0",
|
||||
"@octokit/types": "^13.0.0",
|
||||
"before-after-hook": "^2.2.0",
|
||||
"universal-user-agent": "^6.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 18"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/endpoint": {
|
||||
"version": "6.0.12",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-6.0.12.tgz",
|
||||
"integrity": "sha512-lF3puPwkQWGfkMClXb4k/eUT/nZKQfxinRWJrdZaJO85Dqwo/G0yOC434Jr2ojwafWJMYqFGFa5ms4jJUgujdA==",
|
||||
"version": "9.0.6",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-9.0.6.tgz",
|
||||
"integrity": "sha512-H1fNTMA57HbkFESSt3Y9+FBICv+0jFceJFPWDePYlR/iMGrwM5ph+Dd4XRQs+8X+PUFURLQgX9ChPfhJ/1uNQw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@octokit/types": "^6.0.3",
|
||||
"is-plain-object": "^5.0.0",
|
||||
"@octokit/types": "^13.1.0",
|
||||
"universal-user-agent": "^6.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 18"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/graphql": {
|
||||
"version": "4.8.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-4.8.0.tgz",
|
||||
"integrity": "sha512-0gv+qLSBLKF0z8TKaSKTsS39scVKF9dbMxJpj3U0vC7wjNWFuIpL/z76Qe2fiuCbDRcJSavkXsVtMS6/dtQQsg==",
|
||||
"version": "7.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-7.1.0.tgz",
|
||||
"integrity": "sha512-r+oZUH7aMFui1ypZnAvZmn0KSqAUgE1/tUXIWaqUCa1758ts/Jio84GZuzsvUkme98kv0WFY8//n0J1Z+vsIsQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@octokit/request": "^5.6.0",
|
||||
"@octokit/types": "^6.0.3",
|
||||
"@octokit/request": "^8.3.0",
|
||||
"@octokit/types": "^13.0.0",
|
||||
"universal-user-agent": "^6.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 18"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/openapi-types": {
|
||||
"version": "12.11.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-12.11.0.tgz",
|
||||
"integrity": "sha512-VsXyi8peyRq9PqIz/tpqiL2w3w80OgVMwBHltTml3LmVvXiphgeqmY9mvBw9Wu7e0QWk/fqD37ux8yP5uVekyQ=="
|
||||
"version": "23.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-23.0.1.tgz",
|
||||
"integrity": "sha512-izFjMJ1sir0jn0ldEKhZ7xegCTj/ObmEDlEfpFrx4k/JyZSMRHbO3/rBwgE7f3m2DHt+RrNGIVw4wSmwnm3t/g==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@octokit/plugin-paginate-rest": {
|
||||
"version": "2.21.3",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-2.21.3.tgz",
|
||||
"integrity": "sha512-aCZTEf0y2h3OLbrgKkrfFdjRL6eSOo8komneVQJnYecAxIej7Bafor2xhuDJOIFau4pk0i/P28/XgtbyPF0ZHw==",
|
||||
"version": "9.2.2",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-9.2.2.tgz",
|
||||
"integrity": "sha512-u3KYkGF7GcZnSD/3UP0S7K5XUFT2FkOQdcfXZGZQPGv3lm4F2Xbf71lvjldr8c1H3nNbF+33cLEkWYbokGWqiQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@octokit/types": "^6.40.0"
|
||||
"@octokit/types": "^12.6.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 18"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@octokit/core": ">=2"
|
||||
"@octokit/core": "5"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/plugin-paginate-rest/node_modules/@octokit/openapi-types": {
|
||||
"version": "20.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-20.0.0.tgz",
|
||||
"integrity": "sha512-EtqRBEjp1dL/15V7WiX5LJMIxxkdiGJnabzYx5Apx4FkQIFgAfKumXeYAqqJCj1s+BMX4cPFIFC4OLCR6stlnA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@octokit/plugin-paginate-rest/node_modules/@octokit/types": {
|
||||
"version": "12.6.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-12.6.0.tgz",
|
||||
"integrity": "sha512-1rhSOfRa6H9w4YwK0yrf5faDaDTb+yLyBUKOCV4xtCDB5VmIPqd/v9yr9o6SAzOAlRxMiRiCic6JVM1/kunVkw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@octokit/openapi-types": "^20.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/plugin-rest-endpoint-methods": {
|
||||
"version": "5.16.2",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-5.16.2.tgz",
|
||||
"integrity": "sha512-8QFz29Fg5jDuTPXVtey05BLm7OB+M8fnvE64RNegzX7U+5NUXcOcnpTIK0YfSHBg8gYd0oxIq3IZTe9SfPZiRw==",
|
||||
"version": "10.4.1",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-10.4.1.tgz",
|
||||
"integrity": "sha512-xV1b+ceKV9KytQe3zCVqjg+8GTGfDYwaT1ATU5isiUyVtlVAO3HNdzpS4sr4GBx4hxQ46s7ITtZrAsxG22+rVg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@octokit/types": "^6.39.0",
|
||||
"deprecation": "^2.3.1"
|
||||
"@octokit/types": "^12.6.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 18"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@octokit/core": ">=3"
|
||||
"@octokit/core": "5"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/plugin-rest-endpoint-methods/node_modules/@octokit/openapi-types": {
|
||||
"version": "20.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-20.0.0.tgz",
|
||||
"integrity": "sha512-EtqRBEjp1dL/15V7WiX5LJMIxxkdiGJnabzYx5Apx4FkQIFgAfKumXeYAqqJCj1s+BMX4cPFIFC4OLCR6stlnA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@octokit/plugin-rest-endpoint-methods/node_modules/@octokit/types": {
|
||||
"version": "12.6.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-12.6.0.tgz",
|
||||
"integrity": "sha512-1rhSOfRa6H9w4YwK0yrf5faDaDTb+yLyBUKOCV4xtCDB5VmIPqd/v9yr9o6SAzOAlRxMiRiCic6JVM1/kunVkw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@octokit/openapi-types": "^20.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/request": {
|
||||
"version": "5.6.3",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/request/-/request-5.6.3.tgz",
|
||||
"integrity": "sha512-bFJl0I1KVc9jYTe9tdGGpAMPy32dLBXXo1dS/YwSCTL/2nd9XeHsY616RE3HPXDVk+a+dBuzyz5YdlXwcDTr2A==",
|
||||
"version": "8.4.1",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/request/-/request-8.4.1.tgz",
|
||||
"integrity": "sha512-qnB2+SY3hkCmBxZsR/MPCybNmbJe4KAlfWErXq+rBKkQJlbjdJeS85VI9r8UqeLYLvnAenU8Q1okM/0MBsAGXw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@octokit/endpoint": "^6.0.1",
|
||||
"@octokit/request-error": "^2.1.0",
|
||||
"@octokit/types": "^6.16.1",
|
||||
"is-plain-object": "^5.0.0",
|
||||
"node-fetch": "^2.6.7",
|
||||
"@octokit/endpoint": "^9.0.6",
|
||||
"@octokit/request-error": "^5.1.1",
|
||||
"@octokit/types": "^13.1.0",
|
||||
"universal-user-agent": "^6.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 18"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/request-error": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-2.1.0.tgz",
|
||||
"integrity": "sha512-1VIvgXxs9WHSjicsRwq8PlR2LR2x6DwsJAaFgzdi0JfJoGSO8mYI/cHJQ+9FbN21aa+DrgNLnwObmyeSC8Rmpg==",
|
||||
"version": "5.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-5.1.1.tgz",
|
||||
"integrity": "sha512-v9iyEQJH6ZntoENr9/yXxjuezh4My67CBSu9r6Ve/05Iu5gNgnisNWOsoJHTP6k0Rr0+HQIpnH+kyammu90q/g==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@octokit/types": "^6.0.3",
|
||||
"@octokit/types": "^13.1.0",
|
||||
"deprecation": "^2.0.0",
|
||||
"once": "^1.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/request/node_modules/node-fetch": {
|
||||
"version": "2.7.0",
|
||||
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz",
|
||||
"integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==",
|
||||
"dependencies": {
|
||||
"whatwg-url": "^5.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "4.x || >=6.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"encoding": "^0.1.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"encoding": {
|
||||
"optional": true
|
||||
}
|
||||
"node": ">= 18"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/rest": {
|
||||
@@ -206,89 +247,6 @@
|
||||
"node": ">= 18"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/rest/node_modules/@octokit/auth-token": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-4.0.0.tgz",
|
||||
"integrity": "sha512-tY/msAuJo6ARbK6SPIxZrPBms3xPbfwBrulZe0Wtr/DIY9lje2HeV1uoebShn6mx7SjCHif6EjMvoREj+gZ+SA==",
|
||||
"engines": {
|
||||
"node": ">= 18"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/rest/node_modules/@octokit/core": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/core/-/core-5.0.0.tgz",
|
||||
"integrity": "sha512-YbAtMWIrbZ9FCXbLwT9wWB8TyLjq9mxpKdgB3dUNxQcIVTf9hJ70gRPwAcqGZdY6WdJPZ0I7jLaaNDCiloGN2A==",
|
||||
"dependencies": {
|
||||
"@octokit/auth-token": "^4.0.0",
|
||||
"@octokit/graphql": "^7.0.0",
|
||||
"@octokit/request": "^8.0.2",
|
||||
"@octokit/request-error": "^5.0.0",
|
||||
"@octokit/types": "^11.0.0",
|
||||
"before-after-hook": "^2.2.0",
|
||||
"universal-user-agent": "^6.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 18"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/rest/node_modules/@octokit/endpoint": {
|
||||
"version": "9.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-9.0.0.tgz",
|
||||
"integrity": "sha512-szrQhiqJ88gghWY2Htt8MqUDO6++E/EIXqJ2ZEp5ma3uGS46o7LZAzSLt49myB7rT+Hfw5Y6gO3LmOxGzHijAQ==",
|
||||
"dependencies": {
|
||||
"@octokit/types": "^11.0.0",
|
||||
"is-plain-object": "^5.0.0",
|
||||
"universal-user-agent": "^6.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 18"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/rest/node_modules/@octokit/graphql": {
|
||||
"version": "7.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-7.0.1.tgz",
|
||||
"integrity": "sha512-T5S3oZ1JOE58gom6MIcrgwZXzTaxRnxBso58xhozxHpOqSTgDS6YNeEUvZ/kRvXgPrRz/KHnZhtb7jUMRi9E6w==",
|
||||
"dependencies": {
|
||||
"@octokit/request": "^8.0.1",
|
||||
"@octokit/types": "^11.0.0",
|
||||
"universal-user-agent": "^6.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 18"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/rest/node_modules/@octokit/openapi-types": {
|
||||
"version": "18.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-18.0.0.tgz",
|
||||
"integrity": "sha512-V8GImKs3TeQRxRtXFpG2wl19V7444NIOTDF24AWuIbmNaNYOQMWRbjcGDXV5B+0n887fgDcuMNOmlul+k+oJtw=="
|
||||
},
|
||||
"node_modules/@octokit/rest/node_modules/@octokit/plugin-paginate-rest": {
|
||||
"version": "9.2.1",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-9.2.1.tgz",
|
||||
"integrity": "sha512-wfGhE/TAkXZRLjksFXuDZdmGnJQHvtU/joFQdweXUgzo1XwvBCD4o4+75NtFfjfLK5IwLf9vHTfSiU3sLRYpRw==",
|
||||
"dependencies": {
|
||||
"@octokit/types": "^12.6.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 18"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@octokit/core": "5"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/rest/node_modules/@octokit/plugin-paginate-rest/node_modules/@octokit/openapi-types": {
|
||||
"version": "20.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-20.0.0.tgz",
|
||||
"integrity": "sha512-EtqRBEjp1dL/15V7WiX5LJMIxxkdiGJnabzYx5Apx4FkQIFgAfKumXeYAqqJCj1s+BMX4cPFIFC4OLCR6stlnA=="
|
||||
},
|
||||
"node_modules/@octokit/rest/node_modules/@octokit/plugin-paginate-rest/node_modules/@octokit/types": {
|
||||
"version": "12.6.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-12.6.0.tgz",
|
||||
"integrity": "sha512-1rhSOfRa6H9w4YwK0yrf5faDaDTb+yLyBUKOCV4xtCDB5VmIPqd/v9yr9o6SAzOAlRxMiRiCic6JVM1/kunVkw==",
|
||||
"dependencies": {
|
||||
"@octokit/openapi-types": "^20.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/rest/node_modules/@octokit/plugin-request-log": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-4.0.0.tgz",
|
||||
@@ -300,75 +258,13 @@
|
||||
"@octokit/core": ">=5"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/rest/node_modules/@octokit/plugin-rest-endpoint-methods": {
|
||||
"version": "10.4.1",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-10.4.1.tgz",
|
||||
"integrity": "sha512-xV1b+ceKV9KytQe3zCVqjg+8GTGfDYwaT1ATU5isiUyVtlVAO3HNdzpS4sr4GBx4hxQ46s7ITtZrAsxG22+rVg==",
|
||||
"dependencies": {
|
||||
"@octokit/types": "^12.6.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 18"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@octokit/core": "5"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/rest/node_modules/@octokit/plugin-rest-endpoint-methods/node_modules/@octokit/openapi-types": {
|
||||
"version": "20.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-20.0.0.tgz",
|
||||
"integrity": "sha512-EtqRBEjp1dL/15V7WiX5LJMIxxkdiGJnabzYx5Apx4FkQIFgAfKumXeYAqqJCj1s+BMX4cPFIFC4OLCR6stlnA=="
|
||||
},
|
||||
"node_modules/@octokit/rest/node_modules/@octokit/plugin-rest-endpoint-methods/node_modules/@octokit/types": {
|
||||
"version": "12.6.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-12.6.0.tgz",
|
||||
"integrity": "sha512-1rhSOfRa6H9w4YwK0yrf5faDaDTb+yLyBUKOCV4xtCDB5VmIPqd/v9yr9o6SAzOAlRxMiRiCic6JVM1/kunVkw==",
|
||||
"dependencies": {
|
||||
"@octokit/openapi-types": "^20.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/rest/node_modules/@octokit/request": {
|
||||
"version": "8.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/request/-/request-8.1.1.tgz",
|
||||
"integrity": "sha512-8N+tdUz4aCqQmXl8FpHYfKG9GelDFd7XGVzyN8rc6WxVlYcfpHECnuRkgquzz+WzvHTK62co5di8gSXnzASZPQ==",
|
||||
"dependencies": {
|
||||
"@octokit/endpoint": "^9.0.0",
|
||||
"@octokit/request-error": "^5.0.0",
|
||||
"@octokit/types": "^11.1.0",
|
||||
"is-plain-object": "^5.0.0",
|
||||
"universal-user-agent": "^6.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 18"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/rest/node_modules/@octokit/request-error": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-5.0.0.tgz",
|
||||
"integrity": "sha512-1ue0DH0Lif5iEqT52+Rf/hf0RmGO9NWFjrzmrkArpG9trFfDM/efx00BJHdLGuro4BR/gECxCU2Twf5OKrRFsQ==",
|
||||
"dependencies": {
|
||||
"@octokit/types": "^11.0.0",
|
||||
"deprecation": "^2.0.0",
|
||||
"once": "^1.4.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 18"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/rest/node_modules/@octokit/types": {
|
||||
"version": "11.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-11.1.0.tgz",
|
||||
"integrity": "sha512-Fz0+7GyLm/bHt8fwEqgvRBWwIV1S6wRRyq+V6exRKLVWaKGsuy6H9QFYeBVDV7rK6fO3XwHgQOPxv+cLj2zpXQ==",
|
||||
"dependencies": {
|
||||
"@octokit/openapi-types": "^18.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/types": {
|
||||
"version": "6.41.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.41.0.tgz",
|
||||
"integrity": "sha512-eJ2jbzjdijiL3B4PrSQaSjuF2sPEQPVCPzBvTHJD9Nz+9dw2SGH4K4xeQJ77YfTq5bRQ+bD8wT11JbeDPmxmGg==",
|
||||
"version": "13.8.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.8.0.tgz",
|
||||
"integrity": "sha512-x7DjTIbEpEWXK99DMd01QfWy0hd5h4EN+Q7shkdKds3otGQP+oWE/y0A76i1OvH9fygo4ddvNf7ZvF0t78P98A==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@octokit/openapi-types": "^12.11.0"
|
||||
"@octokit/openapi-types": "^23.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@vercel/ncc": {
|
||||
@@ -396,7 +292,8 @@
|
||||
"node_modules/deprecation": {
|
||||
"version": "2.3.1",
|
||||
"resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz",
|
||||
"integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ=="
|
||||
"integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==",
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/fetch-blob": {
|
||||
"version": "3.2.0",
|
||||
@@ -446,14 +343,6 @@
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/is-plain-object": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz",
|
||||
"integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/is-stream": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz",
|
||||
@@ -504,15 +393,11 @@
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
|
||||
"integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"wrappy": "1"
|
||||
}
|
||||
},
|
||||
"node_modules/tr46": {
|
||||
"version": "0.0.3",
|
||||
"resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
|
||||
"integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw=="
|
||||
},
|
||||
"node_modules/tunnel": {
|
||||
"version": "0.0.6",
|
||||
"resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz",
|
||||
@@ -529,6 +414,18 @@
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/undici": {
|
||||
"version": "5.28.5",
|
||||
"resolved": "https://registry.npmjs.org/undici/-/undici-5.28.5.tgz",
|
||||
"integrity": "sha512-zICwjrDrcrUE0pyyJc1I2QzBkLM8FINsgOrt6WjA+BgajVq9Nxu2PbFFXUrAggLfDXlZGZBVZYw7WNV5KiBiBA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@fastify/busboy": "^2.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.0"
|
||||
}
|
||||
},
|
||||
"node_modules/universal-user-agent": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.0.tgz",
|
||||
@@ -550,24 +447,11 @@
|
||||
"node": ">= 8"
|
||||
}
|
||||
},
|
||||
"node_modules/webidl-conversions": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
|
||||
"integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="
|
||||
},
|
||||
"node_modules/whatwg-url": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
|
||||
"integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==",
|
||||
"dependencies": {
|
||||
"tr46": "~0.0.3",
|
||||
"webidl-conversions": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/wrappy": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
||||
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="
|
||||
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
|
||||
"license": "ISC"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@actions/core": "^1.10.1",
|
||||
"@actions/github": "^5.1.1",
|
||||
"@actions/github": "^6.0.0",
|
||||
"@octokit/auth-action": "^4.0.1",
|
||||
"@octokit/rest": "^20.0.2",
|
||||
"hasha": "^5.2.0",
|
||||
|
||||
@@ -27,6 +27,12 @@ on:
|
||||
- '.github/workflows/ci-build.yml'
|
||||
workflow_dispatch:
|
||||
|
||||
concurrency:
|
||||
# only 1 concurrent `ci-build` allowed per branch
|
||||
# https://docs.github.com/en/actions/writing-workflows/workflow-syntax-for-github-actions#example-using-concurrency-and-the-default-behavior
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
build:
|
||||
strategy:
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
name: ci-check-ns-api-version
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- "nym-node-status-api/**"
|
||||
|
||||
env:
|
||||
WORKING_DIRECTORY: "nym-node-status-api/nym-node-status-api"
|
||||
|
||||
jobs:
|
||||
check-if-tag-exists:
|
||||
runs-on: arc-ubuntu-22.04-dind
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Get version from cargo.toml
|
||||
uses: mikefarah/yq@v4.45.1
|
||||
id: get_version
|
||||
with:
|
||||
cmd: yq -oy '.package.version' ${{ env.WORKING_DIRECTORY }}/Cargo.toml
|
||||
|
||||
- name: Check if git tag exists
|
||||
run: |
|
||||
TAG=${{ env.WORKING_DIRECTORY }}-${{ steps.get_version.outputs.result }}
|
||||
if [[ -z "$TAG" ]]; then
|
||||
echo "Tag is empty"
|
||||
exit 1
|
||||
fi
|
||||
git ls-remote --tags origin | awk '{print $2}'
|
||||
if git ls-remote --tags origin | awk '{print $2}' | grep -q "refs/tags/$TAG$" ; then
|
||||
echo "Tag '$TAG' ALREADY EXISTS on the remote"
|
||||
exit 1
|
||||
else
|
||||
echo "Tag '$TAG' does not exist on the remote"
|
||||
fi
|
||||
- name: Check if harbor tag exists
|
||||
run: |
|
||||
TAG=${{ steps.get_version.outputs.result }}
|
||||
registry=https://harbor.nymte.ch
|
||||
repo_name=nym/node-status-api
|
||||
if [[ -z $TAG ]]; then
|
||||
echo "Tag is empty"
|
||||
exit 1
|
||||
fi
|
||||
curl -su ${{ secrets.HARBOR_ROBOT_USERNAME }}:${{ secrets.HARBOR_ROBOT_SECRET }} "$registry/v2/$repo_name/tags/list" | jq
|
||||
exists=$(curl -su ${{ secrets.HARBOR_ROBOT_USERNAME }}:${{ secrets.HARBOR_ROBOT_SECRET }} "$registry/v2/$repo_name/tags/list" | jq --arg tag $TAG '.tags | contains([$tag])' )
|
||||
if [[ $exists = "true" ]]; then
|
||||
echo "Version '$TAG' defined in Cargo.toml ALREADY EXISTS as tag in harbor repo"
|
||||
exit 1
|
||||
elif [[ $exists = "false" ]]; then
|
||||
echo "Version '$TAG' doesn't exist on the remote"
|
||||
else
|
||||
echo "Unknown output '$exists'"
|
||||
exit 1
|
||||
fi
|
||||
@@ -1,6 +0,0 @@
|
||||
[
|
||||
{
|
||||
"rust":"stable",
|
||||
"runOnEvent":"always"
|
||||
}
|
||||
]
|
||||
@@ -31,7 +31,6 @@ jobs:
|
||||
- name: Install Rust stable
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: 1.77
|
||||
target: wasm32-unknown-unknown
|
||||
override: true
|
||||
|
||||
@@ -40,6 +39,9 @@ jobs:
|
||||
with:
|
||||
version: '114'
|
||||
|
||||
- name: Install cosmwasm-check
|
||||
run: cargo install cosmwasm-check
|
||||
|
||||
- name: Build release contracts
|
||||
run: make contracts
|
||||
|
||||
@@ -50,7 +52,6 @@ jobs:
|
||||
run: |
|
||||
cp contracts/target/wasm32-unknown-unknown/release/mixnet_contract.wasm $OUTPUT_DIR
|
||||
cp contracts/target/wasm32-unknown-unknown/release/vesting_contract.wasm $OUTPUT_DIR
|
||||
cp contracts/target/wasm32-unknown-unknown/release/nym_coconut_bandwidth.wasm $OUTPUT_DIR
|
||||
cp contracts/target/wasm32-unknown-unknown/release/nym_coconut_dkg.wasm $OUTPUT_DIR
|
||||
cp contracts/target/wasm32-unknown-unknown/release/cw3_flex_multisig.wasm $OUTPUT_DIR
|
||||
cp contracts/target/wasm32-unknown-unknown/release/cw4_group.wasm $OUTPUT_DIR
|
||||
|
||||
@@ -14,28 +14,12 @@ on:
|
||||
- '.github/workflows/ci-contracts.yml'
|
||||
|
||||
jobs:
|
||||
matrix_prep:
|
||||
runs-on: ubuntu-20.04
|
||||
outputs:
|
||||
matrix: ${{ steps.set-matrix.outputs.matrix }}
|
||||
steps:
|
||||
# creates the matrix strategy from ci-contracts-matrix-includes.json
|
||||
- uses: actions/checkout@v4
|
||||
- id: set-matrix
|
||||
uses: JoshuaTheMiller/conditional-build-matrix@main
|
||||
with:
|
||||
inputFile: '.github/workflows/ci-contracts-matrix-includes.json'
|
||||
filter: '[?runOnEvent==`${{ github.event_name }}` || runOnEvent==`always`]'
|
||||
build:
|
||||
# since it's going to be compiled into wasm, there's absolutely
|
||||
# no point in running CI on different OS-es
|
||||
runs-on: ubuntu-20.04
|
||||
env:
|
||||
CARGO_TERM_COLOR: always
|
||||
needs: matrix_prep
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix: ${{fromJson(needs.matrix_prep.outputs.matrix)}}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
@@ -43,11 +27,19 @@ jobs:
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
profile: minimal
|
||||
toolchain: ${{ matrix.rust }}
|
||||
toolchain: stable
|
||||
target: wasm32-unknown-unknown
|
||||
override: true
|
||||
components: rustfmt, clippy
|
||||
|
||||
- name: Install cosmwasm-check
|
||||
run: cargo install cosmwasm-check
|
||||
|
||||
- name: Install wasm-opt
|
||||
uses: ./.github/actions/install-wasm-opt
|
||||
with:
|
||||
version: '114'
|
||||
|
||||
- name: Build contracts
|
||||
uses: actions-rs/cargo@v1
|
||||
env:
|
||||
@@ -73,3 +65,7 @@ jobs:
|
||||
with:
|
||||
command: clippy
|
||||
args: --lib --manifest-path contracts/Cargo.toml --workspace --all-targets -- -D warnings
|
||||
|
||||
- name: Check chain compatibility against release build
|
||||
# this will build contracts in release mode, run wasm-opt and finally cosmwasm-check
|
||||
run: make contracts
|
||||
|
||||
@@ -11,6 +11,8 @@ on:
|
||||
jobs:
|
||||
build:
|
||||
runs-on: arc-ubuntu-20.04
|
||||
env:
|
||||
RUSTUP_PERMIT_COPY_RENAME: 1
|
||||
defaults:
|
||||
run:
|
||||
working-directory: documentation/docs
|
||||
|
||||
@@ -16,6 +16,8 @@ on:
|
||||
jobs:
|
||||
build:
|
||||
runs-on: arc-ubuntu-20.04
|
||||
env:
|
||||
RUSTUP_PERMIT_COPY_RENAME: 1
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: rlespinasse/github-slug-action@v3.x
|
||||
@@ -42,7 +44,7 @@ jobs:
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: '1.20'
|
||||
go-version: "1.23.7"
|
||||
|
||||
- name: Install
|
||||
run: yarn
|
||||
|
||||
@@ -14,6 +14,7 @@ jobs:
|
||||
runs-on: arc-ubuntu-20.04
|
||||
env:
|
||||
CARGO_TERM_COLOR: always
|
||||
RUSTUP_PERMIT_COPY_RENAME: 1
|
||||
steps:
|
||||
- name: Install Dependencies (Linux)
|
||||
run: sudo apt-get update && sudo apt-get -y install libwebkit2gtk-4.0-dev build-essential curl wget libssl-dev libgtk-3-dev squashfs-tools
|
||||
|
||||
@@ -10,66 +10,66 @@ jobs:
|
||||
build:
|
||||
runs-on: custom-linux
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Install rsync
|
||||
run: sudo apt-get install rsync
|
||||
continue-on-error: true
|
||||
- name: Install rsync
|
||||
run: sudo apt-get install rsync
|
||||
continue-on-error: true
|
||||
|
||||
- uses: rlespinasse/github-slug-action@v3.x
|
||||
- uses: rlespinasse/github-slug-action@v3.x
|
||||
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 18
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 20
|
||||
|
||||
- name: Setup yarn
|
||||
run: npm install -g yarn
|
||||
- name: Setup yarn
|
||||
run: npm install -g yarn
|
||||
|
||||
- name: Install Rust stable
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: stable
|
||||
- name: Install Rust stable
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: stable
|
||||
|
||||
- name: Install wasm-pack
|
||||
run: curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh
|
||||
- name: Install wasm-pack
|
||||
run: curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh
|
||||
|
||||
- name: Build dependencies
|
||||
run: yarn && yarn build
|
||||
- name: Build dependencies
|
||||
run: yarn && yarn build
|
||||
|
||||
- name: Build storybook
|
||||
run: yarn storybook:build
|
||||
working-directory: ./nym-wallet
|
||||
- name: Build storybook
|
||||
run: yarn storybook:build
|
||||
working-directory: ./nym-wallet
|
||||
|
||||
- name: Deploy branch to CI www (storybook)
|
||||
continue-on-error: true
|
||||
uses: easingthemes/ssh-deploy@main
|
||||
env:
|
||||
SSH_PRIVATE_KEY: ${{ secrets.CI_WWW_SSH_PRIVATE_KEY }}
|
||||
ARGS: "-rltgoDzvO --delete"
|
||||
SOURCE: "nym-wallet/storybook-static/"
|
||||
REMOTE_HOST: ${{ secrets.CI_WWW_REMOTE_HOST }}
|
||||
REMOTE_USER: ${{ secrets.CI_WWW_REMOTE_USER }}
|
||||
TARGET: ${{ secrets.CI_WWW_REMOTE_TARGET }}/wallet-${{ env.GITHUB_REF_SLUG }}
|
||||
EXCLUDE: "/dist/, /node_modules/"
|
||||
- name: Deploy branch to CI www (storybook)
|
||||
continue-on-error: true
|
||||
uses: easingthemes/ssh-deploy@main
|
||||
env:
|
||||
SSH_PRIVATE_KEY: ${{ secrets.CI_WWW_SSH_PRIVATE_KEY }}
|
||||
ARGS: "-rltgoDzvO --delete"
|
||||
SOURCE: "nym-wallet/storybook-static/"
|
||||
REMOTE_HOST: ${{ secrets.CI_WWW_REMOTE_HOST }}
|
||||
REMOTE_USER: ${{ secrets.CI_WWW_REMOTE_USER }}
|
||||
TARGET: ${{ secrets.CI_WWW_REMOTE_TARGET }}/wallet-${{ env.GITHUB_REF_SLUG }}
|
||||
EXCLUDE: "/dist/, /node_modules/"
|
||||
|
||||
- name: Matrix - Node Install
|
||||
run: npm install
|
||||
working-directory: .github/workflows/support-files
|
||||
- name: Matrix - Node Install
|
||||
run: npm install
|
||||
working-directory: .github/workflows/support-files
|
||||
|
||||
- name: Matrix - Send Notification
|
||||
env:
|
||||
NYM_NOTIFICATION_KIND: nym-wallet
|
||||
NYM_PROJECT_NAME: "nym-wallet"
|
||||
NYM_CI_WWW_BASE: "${{ secrets.NYM_CI_WWW_BASE }}"
|
||||
NYM_CI_WWW_LOCATION: "wallet-${{ env.GITHUB_REF_SLUG }}"
|
||||
GIT_COMMIT_MESSAGE: "${{ github.event.head_commit.message }}"
|
||||
GIT_BRANCH: "${GITHUB_REF##*/}"
|
||||
IS_SUCCESS: "${{ job.status == 'success' }}"
|
||||
MATRIX_SERVER: "${{ secrets.MATRIX_SERVER }}"
|
||||
MATRIX_ROOM: "${{ secrets.MATRIX_ROOM }}"
|
||||
MATRIX_USER_ID: "${{ secrets.MATRIX_USER_ID }}"
|
||||
MATRIX_TOKEN: "${{ secrets.MATRIX_TOKEN }}"
|
||||
MATRIX_DEVICE_ID: "${{ secrets.MATRIX_DEVICE_ID }}"
|
||||
uses: docker://keybaseio/client:stable-node
|
||||
with:
|
||||
args: .github/workflows/support-files/notifications/entry_point.sh
|
||||
- name: Matrix - Send Notification
|
||||
env:
|
||||
NYM_NOTIFICATION_KIND: nym-wallet
|
||||
NYM_PROJECT_NAME: "nym-wallet"
|
||||
NYM_CI_WWW_BASE: "${{ secrets.NYM_CI_WWW_BASE }}"
|
||||
NYM_CI_WWW_LOCATION: "wallet-${{ env.GITHUB_REF_SLUG }}"
|
||||
GIT_COMMIT_MESSAGE: "${{ github.event.head_commit.message }}"
|
||||
GIT_BRANCH: "${GITHUB_REF##*/}"
|
||||
IS_SUCCESS: "${{ job.status == 'success' }}"
|
||||
MATRIX_SERVER: "${{ secrets.MATRIX_SERVER }}"
|
||||
MATRIX_ROOM: "${{ secrets.MATRIX_ROOM }}"
|
||||
MATRIX_USER_ID: "${{ secrets.MATRIX_USER_ID }}"
|
||||
MATRIX_TOKEN: "${{ secrets.MATRIX_TOKEN }}"
|
||||
MATRIX_DEVICE_ID: "${{ secrets.MATRIX_DEVICE_ID }}"
|
||||
uses: docker://keybaseio/client:stable-node
|
||||
with:
|
||||
args: .github/workflows/support-files/notifications/entry_point.sh
|
||||
|
||||
@@ -14,6 +14,7 @@ jobs:
|
||||
runs-on: arc-ubuntu-20.04
|
||||
env:
|
||||
CARGO_TERM_COLOR: always
|
||||
RUSTUP_PERMIT_COPY_RENAME: 1
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
@@ -32,7 +33,7 @@ jobs:
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: '1.20'
|
||||
go-version: "1.23.7"
|
||||
|
||||
- name: Install wasm-pack
|
||||
run: curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh
|
||||
|
||||
@@ -2,19 +2,18 @@ name: publish-nym-contracts
|
||||
on:
|
||||
workflow_dispatch:
|
||||
release:
|
||||
types: [created]
|
||||
types: [ created ]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
if: ${{ (startsWith(github.ref, 'refs/tags/nym-contracts-') && github.event_name == 'release') || github.event_name == 'workflow_dispatch' }}
|
||||
runs-on: [self-hosted, custom-ubuntu-20.04]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Install Rust stable
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: 1.77
|
||||
target: wasm32-unknown-unknown
|
||||
override: true
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
platform: [macos-12-large]
|
||||
platform: [macos-15]
|
||||
runs-on: ${{ matrix.platform }}
|
||||
|
||||
outputs:
|
||||
@@ -30,7 +30,7 @@ jobs:
|
||||
- name: Node
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 18
|
||||
node-version: 21
|
||||
- name: Install Rust stable
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
|
||||
@@ -36,7 +36,7 @@ jobs:
|
||||
- name: Node
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 18
|
||||
node-version: 21
|
||||
|
||||
- name: Install Rust stable
|
||||
uses: actions-rs/toolchain@v1
|
||||
|
||||
@@ -49,7 +49,7 @@ jobs:
|
||||
- name: Node
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 18
|
||||
node-version: 21
|
||||
|
||||
- name: Install Rust stable
|
||||
uses: actions-rs/toolchain@v1
|
||||
|
||||
@@ -49,7 +49,7 @@ jobs:
|
||||
"build-tools;$SDK_BUILDTOOLS_VERSION"
|
||||
|
||||
- name: Install Rust toolchain
|
||||
uses: dtolnay/rust-toolchain@1.90.0
|
||||
uses: dtolnay/rust-toolchain@1.100.0
|
||||
|
||||
- name: Install rust android targets
|
||||
run: |
|
||||
|
||||
@@ -31,12 +31,7 @@ jobs:
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: "1.20"
|
||||
|
||||
- name: Install TinyGo
|
||||
uses: acifani/setup-tinygo@v2
|
||||
with:
|
||||
tinygo-version: "0.27.0"
|
||||
go-version: "1.23.7"
|
||||
|
||||
- name: Install dependencies
|
||||
run: yarn
|
||||
|
||||
+184
-10
@@ -4,6 +4,180 @@ Post 1.0.0 release, the changelog format is based on [Keep a Changelog](https://
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
## [2025.6-chuckles] (2025-03-31)
|
||||
|
||||
- Remove Google public DNS ([#5660])
|
||||
- Revert using AsyncWrite sink in IPR ([#5656])
|
||||
- Add fd callback for initial authentication ([#5654])
|
||||
- Add concurrency limit to CI ([#5651])
|
||||
- Remove UNIQUE constraint on node pubkey ([#5649])
|
||||
- Add RUSTUP_PERMIT_COPY_RENAME in two workflows that we forgot about ([#5646])
|
||||
- Upgrade sha2 to workspace version for validator-client ([#5644])
|
||||
- Add max_retransmissions flag on each message ([#5642])
|
||||
- build(deps): bump zip from 2.2.2 to 2.4.1 ([#5639])
|
||||
- build(deps): bump dtolnay/rust-toolchain from 1.90.0 to 1.100.0 ([#5638])
|
||||
- / regenerated yarn.lock ([#5636])
|
||||
- Rework IPR codec to extract out timer and implement AsyncWrite ([#5632])
|
||||
- build(deps): bump tempfile from 3.18.0 to 3.19.0 ([#5631])
|
||||
- build(deps): bump zeroize from 1.6.0 to 1.8.1 ([#5630])
|
||||
- build(deps): bump once_cell from 1.20.3 to 1.21.1 ([#5629])
|
||||
- build(deps): bump uuid from 1.15.1 to 1.16.0 ([#5628])
|
||||
- build(deps): bump celes from 2.5.0 to 2.6.0 ([#5627])
|
||||
- build(deps): bump http from 1.2.0 to 1.3.1 ([#5626])
|
||||
- build(deps): bump humantime from 2.1.0 to 2.2.0 ([#5625])
|
||||
- build(deps): bump the patch-updates group with 8 updates ([#5624])
|
||||
- build(deps): bump @babel/runtime from 7.16.3 to 7.26.10 in /testnet-faucet ([#5621])
|
||||
- Feature/paginated ticketbooks challenge ([#5619])
|
||||
- build(deps-dev): bump webpack from 5.77.0 to 5.98.0 in /wasm/client/internal-dev ([#5615])
|
||||
- build(deps-dev): bump ws from 8.13.0 to 8.18.1 in /wasm/client/internal-dev ([#5614])
|
||||
- build(deps): bump golang.org/x/net from 0.23.0 to 0.36.0 in /wasm/mix-fetch/go-mix-conn ([#5613])
|
||||
- build(deps): bump braces from 3.0.2 to 3.0.3 in /sdk/typescript/packages/mix-fetch-node ([#5612])
|
||||
- Wireguard exit policies (and tests) ([#5557])
|
||||
- Explorer V2 ([#5548])
|
||||
- Clean stale partially received buffers ([#5536])
|
||||
- Corrected typos ([#5497])
|
||||
- build(deps): bump @octokit/plugin-paginate-rest and @actions/github in /.github/actions/nym-hash-releases/src ([#5488])
|
||||
- feature: upgrade cosmwasm to 2.2 ([#5479])
|
||||
- build(deps): bump store2 from 2.14.3 to 2.14.4 ([#5391])
|
||||
- build(deps): bump nanoid from 3.3.7 to 3.3.8 in /documentation/docs ([#5335])
|
||||
- build(deps): bump next from 13.5.7 to 14.2.15 in /documentation/docs ([#5281])
|
||||
- Bump http-proxy-middleware from 2.0.6 to 2.0.7 ([#5019])
|
||||
|
||||
[#5660]: https://github.com/nymtech/nym/pull/5660
|
||||
[#5656]: https://github.com/nymtech/nym/pull/5656
|
||||
[#5654]: https://github.com/nymtech/nym/pull/5654
|
||||
[#5651]: https://github.com/nymtech/nym/pull/5651
|
||||
[#5649]: https://github.com/nymtech/nym/pull/5649
|
||||
[#5646]: https://github.com/nymtech/nym/pull/5646
|
||||
[#5644]: https://github.com/nymtech/nym/pull/5644
|
||||
[#5642]: https://github.com/nymtech/nym/pull/5642
|
||||
[#5639]: https://github.com/nymtech/nym/pull/5639
|
||||
[#5638]: https://github.com/nymtech/nym/pull/5638
|
||||
[#5636]: https://github.com/nymtech/nym/pull/5636
|
||||
[#5632]: https://github.com/nymtech/nym/pull/5632
|
||||
[#5631]: https://github.com/nymtech/nym/pull/5631
|
||||
[#5630]: https://github.com/nymtech/nym/pull/5630
|
||||
[#5629]: https://github.com/nymtech/nym/pull/5629
|
||||
[#5628]: https://github.com/nymtech/nym/pull/5628
|
||||
[#5627]: https://github.com/nymtech/nym/pull/5627
|
||||
[#5626]: https://github.com/nymtech/nym/pull/5626
|
||||
[#5625]: https://github.com/nymtech/nym/pull/5625
|
||||
[#5624]: https://github.com/nymtech/nym/pull/5624
|
||||
[#5621]: https://github.com/nymtech/nym/pull/5621
|
||||
[#5619]: https://github.com/nymtech/nym/pull/5619
|
||||
[#5615]: https://github.com/nymtech/nym/pull/5615
|
||||
[#5614]: https://github.com/nymtech/nym/pull/5614
|
||||
[#5613]: https://github.com/nymtech/nym/pull/5613
|
||||
[#5612]: https://github.com/nymtech/nym/pull/5612
|
||||
[#5557]: https://github.com/nymtech/nym/pull/5557
|
||||
[#5548]: https://github.com/nymtech/nym/pull/5548
|
||||
[#5536]: https://github.com/nymtech/nym/pull/5536
|
||||
[#5497]: https://github.com/nymtech/nym/pull/5497
|
||||
[#5488]: https://github.com/nymtech/nym/pull/5488
|
||||
[#5479]: https://github.com/nymtech/nym/pull/5479
|
||||
[#5391]: https://github.com/nymtech/nym/pull/5391
|
||||
[#5335]: https://github.com/nymtech/nym/pull/5335
|
||||
[#5281]: https://github.com/nymtech/nym/pull/5281
|
||||
[#5019]: https://github.com/nymtech/nym/pull/5019
|
||||
|
||||
## [2025.5-chokito] (2025-03-18)
|
||||
|
||||
- build(deps): bump braces from 3.0.2 to 3.0.3 in /sdk/typescript/packages/nodejs-client ([#5611])
|
||||
- build(deps-dev): bump webpack-dev-middleware from 5.3.3 to 5.3.4 in /wasm/client/internal-dev ([#5610])
|
||||
- Export lane queue lengths in sdk ([#5609])
|
||||
- Chore/more payment watcher debug endpoints ([#5608])
|
||||
- build(deps): bump @babel/helpers from 7.24.4 to 7.26.10 ([#5606])
|
||||
- Chore/update bls12 381 fork ([#5605])
|
||||
- chore: change auth v2 timestamp skew and allow values from the future ([#5604])
|
||||
- Chore/payment watcher debug endpoints ([#5601])
|
||||
- Allow resetting all SURB sender tags ([#5600])
|
||||
- introduce internal tool for checking signer status ([#5598])
|
||||
- build(deps-dev): bump webpack from 5.77.0 to 5.98.0 in /wasm/mix-fetch/internal-dev ([#5597])
|
||||
- build(deps): bump body-parser and express in /wasm/mix-fetch/internal-dev ([#5596])
|
||||
- build(deps): bump serve-static and express in /wasm/mix-fetch/internal-dev ([#5594])
|
||||
- build(deps-dev): bump ws from 8.13.0 to 8.18.1 in /wasm/mix-fetch/internal-dev ([#5593])
|
||||
- build(deps): bump cookie and express in /wasm/client/internal-dev ([#5592])
|
||||
- build(deps): bump cookie and express in /wasm/mix-fetch/internal-dev ([#5591])
|
||||
- build(deps): bump braces from 3.0.2 to 3.0.3 in /wasm/zknym-lib/internal-dev ([#5590])
|
||||
- build(deps): bump webpack-dev-middleware from 5.3.3 to 5.3.4 in /wasm/zknym-lib/internal-dev ([#5589])
|
||||
- build(deps): bump tempfile from 3.17.1 to 3.18.0 ([#5588])
|
||||
- build(deps): bump tokio from 1.43.0 to 1.44.0 ([#5587])
|
||||
- build(deps): bump the patch-updates group with 8 updates ([#5585])
|
||||
- build(deps): bump ring from 0.17.9 to 0.17.13 ([#5583])
|
||||
- delete double memo field in send modal ([#5578])
|
||||
- Server Side internal DoT/DoH opt out ([#5577])
|
||||
- Rust SDK SURB example: change hardcoded file to tempdir ([#5576])
|
||||
- Add /v3/nym-nodes ([#5569])
|
||||
- chore: start sending v2 sphinx packets ([#5554])
|
||||
- build(deps): bump the patch-updates group across 1 directory with 14 updates ([#5549])
|
||||
- build(deps): bump uuid from 1.13.2 to 1.15.1 ([#5542])
|
||||
- build(deps): bump rs_merkle from 1.4.2 to 1.5.0 ([#5541])
|
||||
- feature: v2 authentication request ([#5537])
|
||||
- Set RUSTUP_PERMIT_COPY_RENAME ([#5533])
|
||||
- feature: disallow routing mix packets to nodes not present in the topology ([#5526])
|
||||
- Make "Memo" visible per default on send NYM ([#5524])
|
||||
- feat: make sure any terminated task kills the watcher and write run info to db ([#5517])
|
||||
- Another total_stake SQL fix ([#5516])
|
||||
- Fix total_stake on SQL update ([#5514])
|
||||
- build(deps): bump flate2 from 1.0.35 to 1.1.0 ([#5510])
|
||||
- build(deps): bump itertools from 0.13.0 to 0.14.0 ([#5509])
|
||||
- build(deps): bump the patch-updates group with 2 updates ([#5505])
|
||||
- Treat gateways as Nym Nodes ([#5504])
|
||||
- Update version in Cargo.toml ([#5503])
|
||||
- feat: use ct_eq for checking bearer token ([#5501])
|
||||
- Add extra args for the probe ([#5499])
|
||||
- Fix stats bug & remove HM caching ([#5495])
|
||||
- fix: Cargo.lock for contracts ([#5489])
|
||||
- Display error messages if IPv4 or IPv6 address not found on nymtun0 ([#5465])
|
||||
|
||||
[#5611]: https://github.com/nymtech/nym/pull/5611
|
||||
[#5610]: https://github.com/nymtech/nym/pull/5610
|
||||
[#5609]: https://github.com/nymtech/nym/pull/5609
|
||||
[#5608]: https://github.com/nymtech/nym/pull/5608
|
||||
[#5606]: https://github.com/nymtech/nym/pull/5606
|
||||
[#5605]: https://github.com/nymtech/nym/pull/5605
|
||||
[#5604]: https://github.com/nymtech/nym/pull/5604
|
||||
[#5601]: https://github.com/nymtech/nym/pull/5601
|
||||
[#5600]: https://github.com/nymtech/nym/pull/5600
|
||||
[#5598]: https://github.com/nymtech/nym/pull/5598
|
||||
[#5597]: https://github.com/nymtech/nym/pull/5597
|
||||
[#5596]: https://github.com/nymtech/nym/pull/5596
|
||||
[#5594]: https://github.com/nymtech/nym/pull/5594
|
||||
[#5593]: https://github.com/nymtech/nym/pull/5593
|
||||
[#5592]: https://github.com/nymtech/nym/pull/5592
|
||||
[#5591]: https://github.com/nymtech/nym/pull/5591
|
||||
[#5590]: https://github.com/nymtech/nym/pull/5590
|
||||
[#5589]: https://github.com/nymtech/nym/pull/5589
|
||||
[#5588]: https://github.com/nymtech/nym/pull/5588
|
||||
[#5587]: https://github.com/nymtech/nym/pull/5587
|
||||
[#5585]: https://github.com/nymtech/nym/pull/5585
|
||||
[#5583]: https://github.com/nymtech/nym/pull/5583
|
||||
[#5578]: https://github.com/nymtech/nym/pull/5578
|
||||
[#5577]: https://github.com/nymtech/nym/pull/5577
|
||||
[#5576]: https://github.com/nymtech/nym/pull/5576
|
||||
[#5569]: https://github.com/nymtech/nym/pull/5569
|
||||
[#5554]: https://github.com/nymtech/nym/pull/5554
|
||||
[#5549]: https://github.com/nymtech/nym/pull/5549
|
||||
[#5542]: https://github.com/nymtech/nym/pull/5542
|
||||
[#5541]: https://github.com/nymtech/nym/pull/5541
|
||||
[#5537]: https://github.com/nymtech/nym/pull/5537
|
||||
[#5533]: https://github.com/nymtech/nym/pull/5533
|
||||
[#5526]: https://github.com/nymtech/nym/pull/5526
|
||||
[#5524]: https://github.com/nymtech/nym/pull/5524
|
||||
[#5517]: https://github.com/nymtech/nym/pull/5517
|
||||
[#5516]: https://github.com/nymtech/nym/pull/5516
|
||||
[#5514]: https://github.com/nymtech/nym/pull/5514
|
||||
[#5510]: https://github.com/nymtech/nym/pull/5510
|
||||
[#5509]: https://github.com/nymtech/nym/pull/5509
|
||||
[#5505]: https://github.com/nymtech/nym/pull/5505
|
||||
[#5504]: https://github.com/nymtech/nym/pull/5504
|
||||
[#5503]: https://github.com/nymtech/nym/pull/5503
|
||||
[#5501]: https://github.com/nymtech/nym/pull/5501
|
||||
[#5499]: https://github.com/nymtech/nym/pull/5499
|
||||
[#5495]: https://github.com/nymtech/nym/pull/5495
|
||||
[#5489]: https://github.com/nymtech/nym/pull/5489
|
||||
[#5465]: https://github.com/nymtech/nym/pull/5465
|
||||
|
||||
## [2025.4-dorina-patched] (2025-03-06)
|
||||
|
||||
- use legacy crypto for constructing SURB headers ([#5579])
|
||||
@@ -160,7 +334,7 @@ Post 1.0.0 release, the changelog format is based on [Keep a Changelog](https://
|
||||
- Downgrade harmless log message from info to debug ([#5403])
|
||||
- Redirect from mixnode page to nodes page ([#5397])
|
||||
- chore :update version of chain watcher and validator rewarder ([#5394])
|
||||
- bugfix: correctly handle ingore epoch roles flag ([#5390])
|
||||
- bugfix: correctly handle ignore epoch roles flag ([#5390])
|
||||
- bugfix: terminate mixnet socket listener on shutdown ([#5389])
|
||||
- feat: make client ignore dual mode nodes by default ([#5388])
|
||||
- Handle ecash network errors differently ([#5378])
|
||||
@@ -181,7 +355,7 @@ Post 1.0.0 release, the changelog format is based on [Keep a Changelog](https://
|
||||
- Use expect in geodata test to give error message on failure ([#5314])
|
||||
- feature: periodically remove stale gateway messages ([#5312])
|
||||
- build(deps): bump the patch-updates group across 1 directory with 35 updates ([#5310])
|
||||
- Add dependabot assignes for the root cargo ecosystem ([#5297])
|
||||
- Add dependabot assigns for the root cargo ecosystem ([#5297])
|
||||
- Move tun constants to network defaults ([#5286])
|
||||
- Include IPINFO_API_TOKEN in nightly CI ([#5285])
|
||||
- Nyx Chain Watcher ([#5274])
|
||||
@@ -234,7 +408,7 @@ Post 1.0.0 release, the changelog format is based on [Keep a Changelog](https://
|
||||
|
||||
## [2025.1-reeses] (2025-01-15)
|
||||
|
||||
- Feture/legacy alert ([#5346])
|
||||
- Feature, Future/legacy alert ([#5346])
|
||||
- chore: readjusted --mode behaviour to fix the regression ([#5331])
|
||||
- chore: apply 1.84 linter suggestions ([#5330])
|
||||
- bugfix: make sure refresh data key matches bond info ([#5329])
|
||||
@@ -314,7 +488,7 @@ Post 1.0.0 release, the changelog format is based on [Keep a Changelog](https://
|
||||
|
||||
## [2024.14-crunch-patched] (2024-12-17)
|
||||
|
||||
- Fixes an issue to allow previously registred clients to connect to latest nym-nodes
|
||||
- Fixes an issue to allow previously registered clients to connect to latest nym-nodes
|
||||
- Fixes compatibility issues between nym-nodes and older clients
|
||||
|
||||
## [2024.14-crunch] (2024-12-11)
|
||||
@@ -322,7 +496,7 @@ Post 1.0.0 release, the changelog format is based on [Keep a Changelog](https://
|
||||
- Merge/release/2024.14-crunch ([#5242])
|
||||
- bugfix: added explicit openapi servers to account for route prefixes ([#5237])
|
||||
- Further config score adjustments ([#5225])
|
||||
- feature: remve any filtering on node semver ([#5224])
|
||||
- feature: remove any filtering on node semver ([#5224])
|
||||
- Backport #5218 ([#5220])
|
||||
- Derive serialize for UserAgent (#5210) ([#5217])
|
||||
- dont consider legacy nodes for rewarded set selection ([#5215])
|
||||
@@ -501,7 +675,7 @@ Post 1.0.0 release, the changelog format is based on [Keep a Changelog](https://
|
||||
- bugfix/feature: added NymApiClient method to get all skimmed nodes ([#5062])
|
||||
- Merge1/release/2024.13 magura ([#5061])
|
||||
- added hacky routes to return nymnodes alongside legacy nodes ([#5051])
|
||||
- bugfix: mark migrated gateways as rewarded in the previous epoch in case theyre in the rewarded set ([#5049])
|
||||
- bugfix: mark migrated gateways as rewarded in the previous epoch in case they're, their, there in the rewarded set ([#5049])
|
||||
- bugfix: adjust runtime storage migration ([#5047])
|
||||
- bugfix: supersede 'cb13be27f8f61d9ae74d924e85d2e6787895eb14' by using… ([#5046])
|
||||
- bugfix: restore default http port for nym-api ([#5045])
|
||||
@@ -562,7 +736,7 @@ Post 1.0.0 release, the changelog format is based on [Keep a Changelog](https://
|
||||
- Fix broken build after merge ([#4937])
|
||||
- bugfix: correctly paginate through 'search_tx' endpoint ([#4936])
|
||||
- Add more conversions for responses of authenticator messages ([#4929])
|
||||
- Directory Sevices v2.1 ([#4903])
|
||||
- Directory Services, Devices v2.1 ([#4903])
|
||||
- Migrate Legacy Node (Frontend) ([#4826])
|
||||
- Fix critical issues SI84 and SI85 from Cure53 ([#4758])
|
||||
|
||||
@@ -946,7 +1120,7 @@ Post 1.0.0 release, the changelog format is based on [Keep a Changelog](https://
|
||||
- Remove stale peers ([#4640])
|
||||
- Add generic wg private network routing ([#4636])
|
||||
- Feature/new node endpoints ([#4635])
|
||||
- standarised ContractBuildInformation and added it to all contracts ([#4631])
|
||||
- standardised ContractBuildInformation and added it to all contracts ([#4631])
|
||||
- validate nym-node public ips on startup ([#4630])
|
||||
- Bump defguard wg ([#4625])
|
||||
- Fix cargo warnings ([#4624])
|
||||
@@ -1567,7 +1741,7 @@ Post 1.0.0 release, the changelog format is based on [Keep a Changelog](https://
|
||||
- clean-up nym-api startup arguments/flags to use clap 3 and its macro-derived arguments ([#2772])
|
||||
- renamed all references to validator_api to nym_api
|
||||
- renamed all references to nymd to nyxd ([#2696])
|
||||
- all-binaries: standarised argument names (note: old names should still be accepted) ([#2762]
|
||||
- all-binaries: standardised argument names (note: old names should still be accepted) ([#2762]
|
||||
|
||||
### Fixed
|
||||
|
||||
@@ -2072,7 +2246,7 @@ The release also include some additional work for distributed key generation in
|
||||
- Explorer UI tests missing data-testid [\#903](https://github.com/nymtech/nym/pull/903) ([tommyv1987](https://github.com/tommyv1987))
|
||||
- Fix up Nym-Wallet README.md [\#899](https://github.com/nymtech/nym/pull/899) ([tommyv1987](https://github.com/tommyv1987))
|
||||
- Feature/batch delegator rewarding [\#898](https://github.com/nymtech/nym/pull/898) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- Bug mapp nodemap [\#897](https://github.com/nymtech/nym/pull/897) ([Aid19801](https://github.com/Aid19801))
|
||||
- Bug map nodemap [\#897](https://github.com/nymtech/nym/pull/897) ([Aid19801](https://github.com/Aid19801))
|
||||
- Bug fix/macos keyboard shortcuts [\#896](https://github.com/nymtech/nym/pull/896) ([fmtabbara](https://github.com/fmtabbara))
|
||||
- Add a Mobile Nav to the Network Explorer [\#895](https://github.com/nymtech/nym/pull/895) ([Aid19801](https://github.com/Aid19801))
|
||||
- Only use ts-rs in tests [\#894](https://github.com/nymtech/nym/pull/894) ([durch](https://github.com/durch))
|
||||
|
||||
Generated
+748
-929
File diff suppressed because it is too large
Load Diff
+29
-31
@@ -32,9 +32,8 @@ members = [
|
||||
"common/client-libs/validator-client",
|
||||
"common/commands",
|
||||
"common/config",
|
||||
"common/cosmwasm-smart-contracts/coconut-bandwidth-contract",
|
||||
"common/cosmwasm-smart-contracts/coconut-dkg",
|
||||
"common/cosmwasm-smart-contracts/contracts-common",
|
||||
"common/cosmwasm-smart-contracts/contracts-common", "common/cosmwasm-smart-contracts/easy_addr",
|
||||
"common/cosmwasm-smart-contracts/ecash-contract",
|
||||
"common/cosmwasm-smart-contracts/group-contract",
|
||||
"common/cosmwasm-smart-contracts/mixnet-contract",
|
||||
@@ -98,9 +97,9 @@ members = [
|
||||
"common/wireguard",
|
||||
"common/wireguard-types",
|
||||
"documentation/autodoc",
|
||||
"explorer-api",
|
||||
"explorer-api/explorer-api-requests",
|
||||
"explorer-api/explorer-client",
|
||||
# "explorer-api",
|
||||
# "explorer-api/explorer-api-requests",
|
||||
# "explorer-api/explorer-client",
|
||||
"gateway",
|
||||
"integrations/bity",
|
||||
"nym-api",
|
||||
@@ -153,7 +152,6 @@ members = [
|
||||
default-members = [
|
||||
"clients/native",
|
||||
"clients/socks5",
|
||||
"explorer-api",
|
||||
"nym-api",
|
||||
"nym-credential-proxy/nym-credential-proxy",
|
||||
"nym-node",
|
||||
@@ -194,7 +192,7 @@ ammonia = "4"
|
||||
anyhow = "1.0.97"
|
||||
arc-swap = "1.7.1"
|
||||
argon2 = "0.5.0"
|
||||
async-trait = "0.1.87"
|
||||
async-trait = "0.1.88"
|
||||
axum = "0.7.5"
|
||||
axum-client-ip = "0.6.1"
|
||||
axum-extra = "0.9.4"
|
||||
@@ -205,19 +203,19 @@ bincode = "1.3.3"
|
||||
bip39 = { version = "2.0.0", features = ["zeroize"] }
|
||||
bit-vec = "0.7.0" # can we unify those?
|
||||
bitvec = "1.0.0"
|
||||
blake3 = "1.6.1"
|
||||
blake3 = "1.7.0"
|
||||
bloomfilter = "1.0.14"
|
||||
bs58 = "0.5.1"
|
||||
bytecodec = "0.4.15"
|
||||
bytes = "1.10.1"
|
||||
cargo_metadata = "0.18.1"
|
||||
celes = "2.5.0"
|
||||
celes = "2.6.0"
|
||||
cfg-if = "1.0.0"
|
||||
chacha20 = "0.9.0"
|
||||
chacha20poly1305 = "0.10.1"
|
||||
chrono = "0.4.40"
|
||||
cipher = "0.4.3"
|
||||
clap = "4.5.31"
|
||||
clap = "4.5.34"
|
||||
clap_complete = "4.5"
|
||||
clap_complete_fig = "4.5"
|
||||
colored = "2.2"
|
||||
@@ -242,7 +240,7 @@ dotenvy = "0.15.6"
|
||||
ecdsa = "0.16"
|
||||
ed25519-dalek = "2.1"
|
||||
encoding_rs = "0.8.35"
|
||||
env_logger = "0.11.6"
|
||||
env_logger = "0.11.7"
|
||||
envy = "0.4"
|
||||
etherparse = "0.13.0"
|
||||
eyre = "0.6.9"
|
||||
@@ -264,7 +262,7 @@ http = "1"
|
||||
http-body-util = "0.1"
|
||||
httpcodec = "0.2.3"
|
||||
human-repr = "1.1.0"
|
||||
humantime = "2.1.0"
|
||||
humantime = "2.2.0"
|
||||
humantime-serde = "1.1.1"
|
||||
hyper = "1.6.0"
|
||||
hyper-util = "0.1"
|
||||
@@ -285,7 +283,7 @@ moka = { version = "0.12", features = ["future"] }
|
||||
nix = "0.27.1"
|
||||
notify = "5.1.0"
|
||||
okapi = "0.7.0"
|
||||
once_cell = "1.20.3"
|
||||
once_cell = "1.21.3"
|
||||
opentelemetry = "0.19.0"
|
||||
opentelemetry-jaeger = "0.18.0"
|
||||
parking_lot = "0.12.3"
|
||||
@@ -304,7 +302,7 @@ rand_pcg = "0.3.1"
|
||||
rand_seeder = "0.2.3"
|
||||
rayon = "1.5.1"
|
||||
regex = "1.10.6"
|
||||
reqwest = { version = "0.12.4", default-features = false }
|
||||
reqwest = { version = "0.12.15", default-features = false }
|
||||
rocket = "0.5.0"
|
||||
rocket_cors = "0.6.0"
|
||||
rocket_okapi = "0.8.0"
|
||||
@@ -331,16 +329,16 @@ syn = "1"
|
||||
sysinfo = "0.33.0"
|
||||
tap = "1.0.1"
|
||||
tar = "0.4.44"
|
||||
tempfile = "3.18"
|
||||
tempfile = "3.19"
|
||||
thiserror = "2.0"
|
||||
time = "0.3.39"
|
||||
time = "0.3.41"
|
||||
tokio = "1.44"
|
||||
tokio-postgres = "0.7"
|
||||
tokio-stream = "0.1.17"
|
||||
tokio-test = "0.4.4"
|
||||
tokio-tun = "0.11.5"
|
||||
tokio-tungstenite = { version = "0.20.1" }
|
||||
tokio-util = "0.7.13"
|
||||
tokio-util = "0.7.14"
|
||||
toml = "0.8.20"
|
||||
tower = "0.5.2"
|
||||
tower-http = "0.5.2"
|
||||
@@ -349,9 +347,10 @@ tracing-log = "0.2"
|
||||
tracing-opentelemetry = "0.19.0"
|
||||
tracing-subscriber = "0.3.19"
|
||||
tracing-tree = "0.2.2"
|
||||
tracing-indicatif = "0.3.9"
|
||||
ts-rs = "10.1.0"
|
||||
tungstenite = { version = "0.20.1", default-features = false }
|
||||
uniffi = "0.29.0"
|
||||
uniffi = "0.29.1"
|
||||
uniffi_build = "0.29.0"
|
||||
url = "2.5"
|
||||
utoipa = "5.2"
|
||||
@@ -362,7 +361,7 @@ vergen = { version = "=8.3.1", default-features = false }
|
||||
walkdir = "2"
|
||||
wasm-bindgen-test = "0.3.49"
|
||||
x25519-dalek = "2.0.0"
|
||||
zeroize = "1.6.0"
|
||||
zeroize = "1.7.0"
|
||||
|
||||
prometheus = { version = "0.13.0" }
|
||||
|
||||
@@ -376,19 +375,18 @@ ff = { version = "0.13.1", default-features = false }
|
||||
subtle = "2.5.0"
|
||||
|
||||
# cosmwasm-related
|
||||
cosmwasm-schema = "=1.4.3"
|
||||
cosmwasm-std = "=1.4.3"
|
||||
# use 0.5.0 as that's the version used by cosmwasm-std 1.4.3
|
||||
cosmwasm-schema = "=2.2.2"
|
||||
cosmwasm-std = "=2.2.2"
|
||||
# use 1.0.1 as that's the version used by cosmwasm-std 2.2.1
|
||||
# (and ideally we don't want to pull the same dependency twice)
|
||||
serde-json-wasm = "=0.5.0"
|
||||
cosmwasm-storage = "=1.4.3"
|
||||
serde-json-wasm = "=1.0.1"
|
||||
# same version as used by cosmwasm
|
||||
cw-utils = "=1.0.1"
|
||||
cw-storage-plus = "=1.2.0"
|
||||
cw2 = { version = "=1.1.2" }
|
||||
cw3 = { version = "=1.1.2" }
|
||||
cw4 = { version = "=1.1.2" }
|
||||
cw-controllers = { version = "=1.1.0" }
|
||||
cw-utils = "=2.0.0"
|
||||
cw-storage-plus = "=2.0.0"
|
||||
cw2 = { version = "=2.0.0" }
|
||||
cw3 = { version = "=2.0.0" }
|
||||
cw4 = { version = "=2.0.0" }
|
||||
cw-controllers = { version = "=2.0.0" }
|
||||
|
||||
# cosmrs-related
|
||||
bip32 = { version = "0.5.3", default-features = false }
|
||||
@@ -403,7 +401,7 @@ prost = { version = "0.13", default-features = false }
|
||||
gloo-utils = "0.2.0"
|
||||
gloo-net = "0.6.0"
|
||||
|
||||
indexed_db_futures = "0.6.0"
|
||||
indexed_db_futures = "0.6.1"
|
||||
js-sys = "0.3.76"
|
||||
serde-wasm-bindgen = "0.6.5"
|
||||
tsify = "0.4.5"
|
||||
|
||||
@@ -133,17 +133,22 @@ clippy: sdk-wasm-lint
|
||||
# Build contracts ready for deploy
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
CONTRACTS=vesting_contract mixnet_contract nym_ecash
|
||||
CONTRACTS=vesting_contract mixnet_contract nym_ecash cw3_flex_multisig cw4_group nym_coconut_dkg
|
||||
CONTRACTS_WASM=$(addsuffix .wasm, $(CONTRACTS))
|
||||
CONTRACTS_OUT_DIR=contracts/target/wasm32-unknown-unknown/release
|
||||
|
||||
contracts: build-release-contracts wasm-opt-contracts
|
||||
contracts: build-release-contracts wasm-opt-contracts cosmwasm-check-contracts
|
||||
|
||||
wasm-opt-contracts:
|
||||
for contract in $(CONTRACTS_WASM); do \
|
||||
wasm-opt --signext-lowering -Os $(CONTRACTS_OUT_DIR)/$$contract -o $(CONTRACTS_OUT_DIR)/$$contract; \
|
||||
done
|
||||
|
||||
cosmwasm-check-contracts:
|
||||
for contract in $(CONTRACTS_WASM); do \
|
||||
cosmwasm-check $(CONTRACTS_OUT_DIR)/$$contract; \
|
||||
done
|
||||
|
||||
# Consider adding 's' to make plural consistent (beware: used in github workflow)
|
||||
contract-schema:
|
||||
$(MAKE) -C contracts schema
|
||||
@@ -152,18 +157,9 @@ contract-schema:
|
||||
# Convenience targets for crates that are already part of the main workspace
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
build-explorer-api:
|
||||
cargo build -p explorer-api
|
||||
|
||||
build-nym-cli:
|
||||
cargo build -p nym-cli --release
|
||||
|
||||
build-nym-gateway:
|
||||
cargo build -p nym-gateway --release
|
||||
|
||||
build-nym-mixnode:
|
||||
cargo build -p nym-mixnode --release
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Misc
|
||||
# -----------------------------------------------------------------------------
|
||||
@@ -176,13 +172,7 @@ run-api-tests:
|
||||
cd nym-api/tests/functional_test && yarn test:qa
|
||||
|
||||
# Build debian package, and update PPA
|
||||
deb-mixnode: build-nym-mixnode
|
||||
cargo deb -p nym-mixnode
|
||||
|
||||
deb-gateway: build-nym-gateway
|
||||
cargo deb -p nym-gateway
|
||||
|
||||
deb-cli: build-nym-cli
|
||||
cargo deb -p nym-cli
|
||||
|
||||
deb: deb-mixnode deb-gateway deb-cli
|
||||
deb: deb-cli
|
||||
|
||||
@@ -67,3 +67,13 @@ As a general approach, licensing is as follows this pattern:
|
||||
- documentation is Apache 2.0 or CC0-1.0
|
||||
|
||||
Nym Node Operators and Validators Terms and Conditions can be found [here](https://nym.com/operators-validators-terms).
|
||||
|
||||
## Getting Started
|
||||
|
||||
```bash
|
||||
yarn install
|
||||
```
|
||||
|
||||
```bash
|
||||
yarn build
|
||||
```
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "nym-client"
|
||||
version = "1.1.51"
|
||||
version = "1.1.52"
|
||||
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>", "Jędrzej Stuczyński <andrew@nymtech.net>"]
|
||||
description = "Implementation of the Nym Client"
|
||||
edition = "2021"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "nym-socks5-client"
|
||||
version = "1.1.51"
|
||||
version = "1.1.52"
|
||||
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>"]
|
||||
description = "A SOCKS5 localhost proxy that converts incoming messages to Sphinx and sends them to a Nym address"
|
||||
edition = "2021"
|
||||
|
||||
@@ -13,7 +13,7 @@ use std::{fmt, ops::Deref, str::FromStr};
|
||||
#[cfg(feature = "verify")]
|
||||
use hmac::{Hmac, Mac};
|
||||
#[cfg(feature = "verify")]
|
||||
use nym_crypto::asymmetric::encryption::PrivateKey;
|
||||
use nym_crypto::asymmetric::encryption::{PrivateKey, PublicKey};
|
||||
#[cfg(feature = "verify")]
|
||||
use sha2::Sha256;
|
||||
|
||||
@@ -82,16 +82,14 @@ impl GatewayClient {
|
||||
private_ip: IpAddr,
|
||||
nonce: u64,
|
||||
) -> Self {
|
||||
// convert from 1.0 x25519-dalek private key into 2.0 x25519-dalek
|
||||
#[allow(clippy::expect_used)]
|
||||
let static_secret = x25519_dalek::StaticSecret::from(local_secret.to_bytes());
|
||||
let local_public: x25519_dalek::PublicKey = (&static_secret).into();
|
||||
let local_public = PublicKey::from(local_secret);
|
||||
let remote_public = PublicKey::from(remote_public);
|
||||
|
||||
let dh = static_secret.diffie_hellman(&remote_public);
|
||||
let dh = local_secret.diffie_hellman(&remote_public);
|
||||
|
||||
// TODO: change that to use our nym_crypto::hmac module instead
|
||||
#[allow(clippy::expect_used)]
|
||||
let mut mac = HmacSha256::new_from_slice(dh.as_bytes())
|
||||
let mut mac = HmacSha256::new_from_slice(&dh[..])
|
||||
.expect("x25519 shared secret is always 32 bytes long");
|
||||
|
||||
mac.update(local_public.as_bytes());
|
||||
@@ -99,7 +97,7 @@ impl GatewayClient {
|
||||
mac.update(&nonce.to_le_bytes());
|
||||
|
||||
GatewayClient {
|
||||
pub_key: PeerPublicKey::new(local_public),
|
||||
pub_key: PeerPublicKey::new(local_public.into()),
|
||||
private_ip,
|
||||
mac: ClientMac(mac.finalize().into_bytes().to_vec()),
|
||||
}
|
||||
@@ -109,11 +107,8 @@ impl GatewayClient {
|
||||
// Client should perform this step when generating its payload, using its own WG PK
|
||||
#[cfg(feature = "verify")]
|
||||
pub fn verify(&self, gateway_key: &PrivateKey, nonce: u64) -> Result<(), Error> {
|
||||
// convert from 1.0 x25519-dalek private key into 2.0 x25519-dalek
|
||||
#[allow(clippy::expect_used)]
|
||||
let static_secret = x25519_dalek::StaticSecret::from(gateway_key.to_bytes());
|
||||
|
||||
let dh = static_secret.diffie_hellman(&self.pub_key);
|
||||
// use gateways key as a ref to an x25519_dalek key
|
||||
let dh = (gateway_key.as_ref()).diffie_hellman(&self.pub_key);
|
||||
|
||||
// TODO: change that to use our nym_crypto::hmac module instead
|
||||
#[allow(clippy::expect_used)]
|
||||
|
||||
@@ -14,7 +14,7 @@ use std::{fmt, ops::Deref, str::FromStr};
|
||||
#[cfg(feature = "verify")]
|
||||
use hmac::{Hmac, Mac};
|
||||
#[cfg(feature = "verify")]
|
||||
use nym_crypto::asymmetric::encryption::PrivateKey;
|
||||
use nym_crypto::asymmetric::encryption::{PrivateKey, PublicKey};
|
||||
#[cfg(feature = "verify")]
|
||||
use sha2::Sha256;
|
||||
|
||||
@@ -91,16 +91,14 @@ impl GatewayClient {
|
||||
private_ip: IpAddr,
|
||||
nonce: u64,
|
||||
) -> Self {
|
||||
// convert from 1.0 x25519-dalek private key into 2.0 x25519-dalek
|
||||
#[allow(clippy::expect_used)]
|
||||
let static_secret = x25519_dalek::StaticSecret::from(local_secret.to_bytes());
|
||||
let local_public: x25519_dalek::PublicKey = (&static_secret).into();
|
||||
let local_public = PublicKey::from(local_secret);
|
||||
let remote_public = PublicKey::from(remote_public);
|
||||
|
||||
let dh = static_secret.diffie_hellman(&remote_public);
|
||||
let dh = local_secret.diffie_hellman(&remote_public);
|
||||
|
||||
// TODO: change that to use our nym_crypto::hmac module instead
|
||||
#[allow(clippy::expect_used)]
|
||||
let mut mac = HmacSha256::new_from_slice(dh.as_bytes())
|
||||
let mut mac = HmacSha256::new_from_slice(&dh[..])
|
||||
.expect("x25519 shared secret is always 32 bytes long");
|
||||
|
||||
mac.update(local_public.as_bytes());
|
||||
@@ -108,7 +106,7 @@ impl GatewayClient {
|
||||
mac.update(&nonce.to_le_bytes());
|
||||
|
||||
GatewayClient {
|
||||
pub_key: PeerPublicKey::new(local_public),
|
||||
pub_key: PeerPublicKey::new(local_public.into()),
|
||||
private_ip,
|
||||
mac: ClientMac(mac.finalize().into_bytes().to_vec()),
|
||||
}
|
||||
@@ -118,11 +116,8 @@ impl GatewayClient {
|
||||
// Client should perform this step when generating its payload, using its own WG PK
|
||||
#[cfg(feature = "verify")]
|
||||
pub fn verify(&self, gateway_key: &PrivateKey, nonce: u64) -> Result<(), Error> {
|
||||
// convert from 1.0 x25519-dalek private key into 2.0 x25519-dalek
|
||||
#[allow(clippy::expect_used)]
|
||||
let static_secret = x25519_dalek::StaticSecret::from(gateway_key.to_bytes());
|
||||
|
||||
let dh = static_secret.diffie_hellman(&self.pub_key);
|
||||
// use gateways key as a ref to an x25519_dalek key
|
||||
let dh = (gateway_key.as_ref()).diffie_hellman(&self.pub_key);
|
||||
|
||||
// TODO: change that to use our nym_crypto::hmac module instead
|
||||
#[allow(clippy::expect_used)]
|
||||
|
||||
@@ -14,7 +14,7 @@ use std::{fmt, ops::Deref, str::FromStr};
|
||||
#[cfg(feature = "verify")]
|
||||
use hmac::{Hmac, Mac};
|
||||
#[cfg(feature = "verify")]
|
||||
use nym_crypto::asymmetric::encryption::PrivateKey;
|
||||
use nym_crypto::asymmetric::encryption::{PrivateKey, PublicKey};
|
||||
#[cfg(feature = "verify")]
|
||||
use sha2::Sha256;
|
||||
|
||||
@@ -91,16 +91,14 @@ impl GatewayClient {
|
||||
private_ip: IpAddr,
|
||||
nonce: u64,
|
||||
) -> Self {
|
||||
// convert from 1.0 x25519-dalek private key into 2.0 x25519-dalek
|
||||
#[allow(clippy::expect_used)]
|
||||
let static_secret = x25519_dalek::StaticSecret::from(local_secret.to_bytes());
|
||||
let local_public: x25519_dalek::PublicKey = (&static_secret).into();
|
||||
let local_public = PublicKey::from(local_secret);
|
||||
let remote_public = PublicKey::from(remote_public);
|
||||
|
||||
let dh = static_secret.diffie_hellman(&remote_public);
|
||||
let dh = local_secret.diffie_hellman(&remote_public);
|
||||
|
||||
// TODO: change that to use our nym_crypto::hmac module instead
|
||||
#[allow(clippy::expect_used)]
|
||||
let mut mac = HmacSha256::new_from_slice(dh.as_bytes())
|
||||
let mut mac = HmacSha256::new_from_slice(&dh[..])
|
||||
.expect("x25519 shared secret is always 32 bytes long");
|
||||
|
||||
mac.update(local_public.as_bytes());
|
||||
@@ -108,7 +106,7 @@ impl GatewayClient {
|
||||
mac.update(&nonce.to_le_bytes());
|
||||
|
||||
GatewayClient {
|
||||
pub_key: PeerPublicKey::new(local_public),
|
||||
pub_key: PeerPublicKey::new(local_public.into()),
|
||||
private_ip,
|
||||
mac: ClientMac(mac.finalize().into_bytes().to_vec()),
|
||||
}
|
||||
@@ -118,11 +116,8 @@ impl GatewayClient {
|
||||
// Client should perform this step when generating its payload, using its own WG PK
|
||||
#[cfg(feature = "verify")]
|
||||
pub fn verify(&self, gateway_key: &PrivateKey, nonce: u64) -> Result<(), Error> {
|
||||
// convert from 1.0 x25519-dalek private key into 2.0 x25519-dalek
|
||||
#[allow(clippy::expect_used)]
|
||||
let static_secret = x25519_dalek::StaticSecret::from(gateway_key.to_bytes());
|
||||
|
||||
let dh = static_secret.diffie_hellman(&self.pub_key);
|
||||
// use gateways key as a ref to an x25519_dalek key
|
||||
let dh = (gateway_key.as_ref()).diffie_hellman(&self.pub_key);
|
||||
|
||||
// TODO: change that to use our nym_crypto::hmac module instead
|
||||
#[allow(clippy::expect_used)]
|
||||
|
||||
@@ -15,7 +15,7 @@ use std::{fmt, ops::Deref, str::FromStr};
|
||||
#[cfg(feature = "verify")]
|
||||
use hmac::{Hmac, Mac};
|
||||
#[cfg(feature = "verify")]
|
||||
use nym_crypto::asymmetric::encryption::PrivateKey;
|
||||
use nym_crypto::asymmetric::encryption::{PrivateKey, PublicKey};
|
||||
#[cfg(feature = "verify")]
|
||||
use sha2::Sha256;
|
||||
|
||||
@@ -143,16 +143,14 @@ impl GatewayClient {
|
||||
private_ips: IpPair,
|
||||
nonce: u64,
|
||||
) -> Self {
|
||||
// convert from 1.0 x25519-dalek private key into 2.0 x25519-dalek
|
||||
#[allow(clippy::expect_used)]
|
||||
let static_secret = x25519_dalek::StaticSecret::from(local_secret.to_bytes());
|
||||
let local_public: x25519_dalek::PublicKey = (&static_secret).into();
|
||||
let local_public = PublicKey::from(local_secret);
|
||||
let remote_public = PublicKey::from(remote_public);
|
||||
|
||||
let dh = static_secret.diffie_hellman(&remote_public);
|
||||
let dh = local_secret.diffie_hellman(&remote_public);
|
||||
|
||||
// TODO: change that to use our nym_crypto::hmac module instead
|
||||
#[allow(clippy::expect_used)]
|
||||
let mut mac = HmacSha256::new_from_slice(dh.as_bytes())
|
||||
let mut mac = HmacSha256::new_from_slice(&dh[..])
|
||||
.expect("x25519 shared secret is always 32 bytes long");
|
||||
|
||||
mac.update(local_public.as_bytes());
|
||||
@@ -160,7 +158,7 @@ impl GatewayClient {
|
||||
mac.update(&nonce.to_le_bytes());
|
||||
|
||||
GatewayClient {
|
||||
pub_key: PeerPublicKey::new(local_public),
|
||||
pub_key: PeerPublicKey::new(local_public.into()),
|
||||
private_ips,
|
||||
mac: ClientMac(mac.finalize().into_bytes().to_vec()),
|
||||
}
|
||||
@@ -170,11 +168,8 @@ impl GatewayClient {
|
||||
// Client should perform this step when generating its payload, using its own WG PK
|
||||
#[cfg(feature = "verify")]
|
||||
pub fn verify(&self, gateway_key: &PrivateKey, nonce: u64) -> Result<(), Error> {
|
||||
// convert from 1.0 x25519-dalek private key into 2.0 x25519-dalek
|
||||
#[allow(clippy::expect_used)]
|
||||
let static_secret = x25519_dalek::StaticSecret::from(gateway_key.to_bytes());
|
||||
|
||||
let dh = static_secret.diffie_hellman(&self.pub_key);
|
||||
// use gateways key as a ref to an x25519_dalek key
|
||||
let dh = (gateway_key.as_ref()).diffie_hellman(&self.pub_key);
|
||||
|
||||
// TODO: change that to use our nym_crypto::hmac module instead
|
||||
#[allow(clippy::expect_used)]
|
||||
|
||||
@@ -15,7 +15,7 @@ use std::{fmt, ops::Deref, str::FromStr};
|
||||
#[cfg(feature = "verify")]
|
||||
use hmac::{Hmac, Mac};
|
||||
#[cfg(feature = "verify")]
|
||||
use nym_crypto::asymmetric::encryption::PrivateKey;
|
||||
use nym_crypto::asymmetric::encryption::{PrivateKey, PublicKey};
|
||||
#[cfg(feature = "verify")]
|
||||
use sha2::Sha256;
|
||||
|
||||
@@ -143,16 +143,14 @@ impl GatewayClient {
|
||||
private_ips: IpPair,
|
||||
nonce: u64,
|
||||
) -> Self {
|
||||
// convert from 1.0 x25519-dalek private key into 2.0 x25519-dalek
|
||||
#[allow(clippy::expect_used)]
|
||||
let static_secret = x25519_dalek::StaticSecret::from(local_secret.to_bytes());
|
||||
let local_public: x25519_dalek::PublicKey = (&static_secret).into();
|
||||
let local_public = PublicKey::from(local_secret);
|
||||
let remote_public = PublicKey::from(remote_public);
|
||||
|
||||
let dh = static_secret.diffie_hellman(&remote_public);
|
||||
let dh = local_secret.diffie_hellman(&remote_public);
|
||||
|
||||
// TODO: change that to use our nym_crypto::hmac module instead
|
||||
#[allow(clippy::expect_used)]
|
||||
let mut mac = HmacSha256::new_from_slice(dh.as_bytes())
|
||||
let mut mac = HmacSha256::new_from_slice(&dh[..])
|
||||
.expect("x25519 shared secret is always 32 bytes long");
|
||||
|
||||
mac.update(local_public.as_bytes());
|
||||
@@ -160,7 +158,7 @@ impl GatewayClient {
|
||||
mac.update(&nonce.to_le_bytes());
|
||||
|
||||
GatewayClient {
|
||||
pub_key: PeerPublicKey::new(local_public),
|
||||
pub_key: PeerPublicKey::new(local_public.into()),
|
||||
private_ips,
|
||||
mac: ClientMac(mac.finalize().into_bytes().to_vec()),
|
||||
}
|
||||
@@ -170,11 +168,8 @@ impl GatewayClient {
|
||||
// Client should perform this step when generating its payload, using its own WG PK
|
||||
#[cfg(feature = "verify")]
|
||||
pub fn verify(&self, gateway_key: &PrivateKey, nonce: u64) -> Result<(), Error> {
|
||||
// convert from 1.0 x25519-dalek private key into 2.0 x25519-dalek
|
||||
#[allow(clippy::expect_used)]
|
||||
let static_secret = x25519_dalek::StaticSecret::from(gateway_key.to_bytes());
|
||||
|
||||
let dh = static_secret.diffie_hellman(&self.pub_key);
|
||||
// use gateways key as a ref to an x25519_dalek key
|
||||
let dh = (gateway_key.as_ref()).diffie_hellman(&self.pub_key);
|
||||
|
||||
// TODO: change that to use our nym_crypto::hmac module instead
|
||||
#[allow(clippy::expect_used)]
|
||||
|
||||
@@ -21,6 +21,7 @@ serde_json = { workspace = true, optional = true }
|
||||
## tracing
|
||||
tracing-subscriber = { workspace = true, features = ["env-filter"], optional = true }
|
||||
tracing-tree = { workspace = true, optional = true }
|
||||
tracing = { workspace = true, optional = true }
|
||||
opentelemetry-jaeger = { workspace = true, features = ["rt-tokio", "collector_client", "isahc_collector_client"], optional = true }
|
||||
tracing-opentelemetry = { workspace = true, optional = true }
|
||||
utoipa = { workspace = true, optional = true }
|
||||
@@ -35,7 +36,7 @@ default = []
|
||||
openapi = ["utoipa"]
|
||||
output_format = ["serde_json", "dep:clap"]
|
||||
bin_info_schema = ["schemars"]
|
||||
basic_tracing = ["tracing-subscriber"]
|
||||
basic_tracing = ["dep:tracing", "tracing-subscriber"]
|
||||
tracing = [
|
||||
"basic_tracing",
|
||||
"tracing-tree",
|
||||
|
||||
@@ -44,10 +44,38 @@ pub fn setup_logging() {
|
||||
.init();
|
||||
}
|
||||
|
||||
// don't call init so that we could attach additional layers
|
||||
#[cfg(feature = "basic_tracing")]
|
||||
pub fn setup_tracing_logger() {
|
||||
let log_builder = tracing_subscriber::fmt()
|
||||
.with_writer(std::io::stderr)
|
||||
pub fn build_tracing_logger() -> impl tracing_subscriber::layer::SubscriberExt {
|
||||
use tracing_subscriber::prelude::*;
|
||||
|
||||
tracing_subscriber::registry()
|
||||
.with(default_tracing_fmt_layer(std::io::stderr))
|
||||
.with(default_tracing_env_filter())
|
||||
}
|
||||
|
||||
#[cfg(feature = "basic_tracing")]
|
||||
pub fn default_tracing_env_filter() -> tracing_subscriber::filter::EnvFilter {
|
||||
if ::std::env::var("RUST_LOG").is_ok() {
|
||||
tracing_subscriber::filter::EnvFilter::from_default_env()
|
||||
} else {
|
||||
// if the env value was not found, default to `INFO` level rather than `ERROR`
|
||||
tracing_subscriber::filter::EnvFilter::builder()
|
||||
.with_default_directive(tracing_subscriber::filter::LevelFilter::INFO.into())
|
||||
.parse_lossy("")
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "basic_tracing")]
|
||||
pub fn default_tracing_fmt_layer<S, W>(
|
||||
writer: W,
|
||||
) -> impl tracing_subscriber::Layer<S> + Sync + Send + 'static
|
||||
where
|
||||
S: tracing::Subscriber + for<'a> tracing_subscriber::registry::LookupSpan<'a>,
|
||||
W: for<'writer> tracing_subscriber::fmt::MakeWriter<'writer> + Sync + Send + 'static,
|
||||
{
|
||||
tracing_subscriber::fmt::layer()
|
||||
.with_writer(writer)
|
||||
// Use a more compact, abbreviated log format
|
||||
.compact()
|
||||
// Display source code file paths
|
||||
@@ -55,18 +83,13 @@ pub fn setup_tracing_logger() {
|
||||
// Display source code line numbers
|
||||
.with_line_number(true)
|
||||
// Don't display the event's target (module path)
|
||||
.with_target(false);
|
||||
.with_target(false)
|
||||
}
|
||||
|
||||
if ::std::env::var("RUST_LOG").is_ok() {
|
||||
log_builder
|
||||
.with_env_filter(tracing_subscriber::filter::EnvFilter::from_default_env())
|
||||
.init()
|
||||
} else {
|
||||
// default to 'Info
|
||||
log_builder
|
||||
.with_max_level(tracing_subscriber::filter::LevelFilter::INFO)
|
||||
.init()
|
||||
}
|
||||
#[cfg(feature = "basic_tracing")]
|
||||
pub fn setup_tracing_logger() {
|
||||
use tracing_subscriber::util::SubscriberInitExt;
|
||||
build_tracing_logger().init()
|
||||
}
|
||||
|
||||
// TODO: This has to be a macro, running it as a function does not work for the file_appender for some reason
|
||||
|
||||
@@ -139,6 +139,8 @@ where
|
||||
let gateway_setup = GatewaySetup::New {
|
||||
specification: selection_spec,
|
||||
available_gateways,
|
||||
#[cfg(unix)]
|
||||
connection_fd_callback: None,
|
||||
};
|
||||
|
||||
let init_details =
|
||||
|
||||
@@ -187,6 +187,8 @@ where
|
||||
let gateway_setup = GatewaySetup::New {
|
||||
specification: selection_spec,
|
||||
available_gateways,
|
||||
#[cfg(unix)]
|
||||
connection_fd_callback: None,
|
||||
};
|
||||
|
||||
let init_details =
|
||||
|
||||
@@ -28,6 +28,7 @@ pub enum InputMessage {
|
||||
recipient: Recipient,
|
||||
data: Vec<u8>,
|
||||
lane: TransmissionLane,
|
||||
max_retransmissions: Option<u32>,
|
||||
},
|
||||
|
||||
/// Creates a message used for a duplex anonymous communication where the recipient
|
||||
@@ -43,6 +44,7 @@ pub enum InputMessage {
|
||||
data: Vec<u8>,
|
||||
reply_surbs: u32,
|
||||
lane: TransmissionLane,
|
||||
max_retransmissions: Option<u32>,
|
||||
},
|
||||
|
||||
/// Attempt to use our internally received and stored `ReplySurb` to send the message back
|
||||
@@ -53,6 +55,7 @@ pub enum InputMessage {
|
||||
recipient_tag: AnonymousSenderTag,
|
||||
data: Vec<u8>,
|
||||
lane: TransmissionLane,
|
||||
max_retransmissions: Option<u32>,
|
||||
},
|
||||
|
||||
MessageWrapper {
|
||||
@@ -92,6 +95,7 @@ impl InputMessage {
|
||||
recipient,
|
||||
data,
|
||||
lane,
|
||||
max_retransmissions: None,
|
||||
};
|
||||
if let Some(packet_type) = packet_type {
|
||||
InputMessage::new_wrapper(message, packet_type)
|
||||
@@ -112,28 +116,7 @@ impl InputMessage {
|
||||
data,
|
||||
reply_surbs,
|
||||
lane,
|
||||
};
|
||||
if let Some(packet_type) = packet_type {
|
||||
InputMessage::new_wrapper(message, packet_type)
|
||||
} else {
|
||||
message
|
||||
}
|
||||
}
|
||||
|
||||
// IMHO `new_anonymous` should take `mix_hops: Option<u8>` as an argument instead of creating
|
||||
// this function, but that would potentially break backwards compatibility with the current API
|
||||
pub fn new_anonymous_with_custom_hops(
|
||||
recipient: Recipient,
|
||||
data: Vec<u8>,
|
||||
reply_surbs: u32,
|
||||
lane: TransmissionLane,
|
||||
packet_type: Option<PacketType>,
|
||||
) -> Self {
|
||||
let message = InputMessage::Anonymous {
|
||||
recipient,
|
||||
data,
|
||||
reply_surbs,
|
||||
lane,
|
||||
max_retransmissions: None,
|
||||
};
|
||||
if let Some(packet_type) = packet_type {
|
||||
InputMessage::new_wrapper(message, packet_type)
|
||||
@@ -152,6 +135,7 @@ impl InputMessage {
|
||||
recipient_tag,
|
||||
data,
|
||||
lane,
|
||||
max_retransmissions: None,
|
||||
};
|
||||
if let Some(packet_type) = packet_type {
|
||||
InputMessage::new_wrapper(message, packet_type)
|
||||
@@ -169,4 +153,34 @@ impl InputMessage {
|
||||
InputMessage::MessageWrapper { message, .. } => message.lane(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_max_retransmissions(&mut self, max_retransmissions: u32) -> &mut Self {
|
||||
match self {
|
||||
InputMessage::Regular {
|
||||
max_retransmissions: m,
|
||||
..
|
||||
}
|
||||
| InputMessage::Anonymous {
|
||||
max_retransmissions: m,
|
||||
..
|
||||
}
|
||||
| InputMessage::Reply {
|
||||
max_retransmissions: m,
|
||||
..
|
||||
} => {
|
||||
*m = Some(max_retransmissions);
|
||||
}
|
||||
InputMessage::Premade { .. } => {}
|
||||
InputMessage::MessageWrapper { message, .. } => {
|
||||
message.set_max_retransmissions(max_retransmissions);
|
||||
}
|
||||
}
|
||||
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_max_retransmissions(mut self, max_retransmissions: u32) -> Self {
|
||||
self.set_max_retransmissions(max_retransmissions);
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,7 +52,7 @@ impl MixTrafficController {
|
||||
let (message_sender, message_receiver) =
|
||||
tokio::sync::mpsc::channel(MIX_MESSAGE_RECEIVER_BUFFER_SIZE);
|
||||
|
||||
let (client_sender, client_receiver) = tokio::sync::mpsc::channel(1);
|
||||
let (client_sender, client_receiver) = tokio::sync::mpsc::channel(8);
|
||||
|
||||
(
|
||||
MixTrafficController {
|
||||
@@ -77,7 +77,7 @@ impl MixTrafficController {
|
||||
) {
|
||||
let (message_sender, message_receiver) =
|
||||
tokio::sync::mpsc::channel(MIX_MESSAGE_RECEIVER_BUFFER_SIZE);
|
||||
let (client_sender, client_receiver) = tokio::sync::mpsc::channel(1);
|
||||
let (client_sender, client_receiver) = tokio::sync::mpsc::channel(8);
|
||||
(
|
||||
MixTrafficController {
|
||||
gateway_transceiver,
|
||||
|
||||
-3
@@ -222,9 +222,6 @@ impl ActionController {
|
||||
|
||||
// note: when the entry expires it's automatically removed from pending_acks_timers
|
||||
fn handle_expired_ack_timer(&mut self, expired_ack: Expired<FragmentIdentifier>) {
|
||||
// I'm honestly not sure how to handle it, because getting it means other things in our
|
||||
// system are already misbehaving. If we ever see this panic, then I guess we should worry
|
||||
// about it. Perhaps just reschedule it at later point?
|
||||
let frag_id = expired_ack.into_inner();
|
||||
|
||||
trace!("{frag_id} has expired");
|
||||
|
||||
+59
-15
@@ -65,11 +65,12 @@ where
|
||||
recipient_tag: AnonymousSenderTag,
|
||||
data: Vec<u8>,
|
||||
lane: TransmissionLane,
|
||||
max_retransmissions: Option<u32>,
|
||||
) {
|
||||
// offload reply handling to the dedicated task
|
||||
if let Err(err) = self
|
||||
.reply_controller_sender
|
||||
.send_reply(recipient_tag, data, lane)
|
||||
if let Err(err) =
|
||||
self.reply_controller_sender
|
||||
.send_reply(recipient_tag, data, lane, max_retransmissions)
|
||||
{
|
||||
if !self.task_client.is_shutdown_poll() {
|
||||
error!("failed to send a reply - {err}");
|
||||
@@ -83,10 +84,11 @@ where
|
||||
content: Vec<u8>,
|
||||
lane: TransmissionLane,
|
||||
packet_type: PacketType,
|
||||
max_retransmissions: Option<u32>,
|
||||
) {
|
||||
if let Err(err) = self
|
||||
.message_handler
|
||||
.try_send_plain_message(recipient, content, lane, packet_type)
|
||||
.try_send_plain_message(recipient, content, lane, packet_type, max_retransmissions)
|
||||
.await
|
||||
{
|
||||
warn!("failed to send a plain message - {err}")
|
||||
@@ -100,10 +102,18 @@ where
|
||||
reply_surbs: u32,
|
||||
lane: TransmissionLane,
|
||||
packet_type: PacketType,
|
||||
max_retransmissions: Option<u32>,
|
||||
) {
|
||||
if let Err(err) = self
|
||||
.message_handler
|
||||
.try_send_message_with_reply_surbs(recipient, content, reply_surbs, lane, packet_type)
|
||||
.try_send_message_with_reply_surbs(
|
||||
recipient,
|
||||
content,
|
||||
reply_surbs,
|
||||
lane,
|
||||
packet_type,
|
||||
max_retransmissions,
|
||||
)
|
||||
.await
|
||||
{
|
||||
warn!("failed to send a repliable message - {err}")
|
||||
@@ -116,25 +126,42 @@ where
|
||||
recipient,
|
||||
data,
|
||||
lane,
|
||||
max_retransmissions,
|
||||
} => {
|
||||
self.handle_plain_message(recipient, data, lane, PacketType::Mix)
|
||||
.await
|
||||
self.handle_plain_message(
|
||||
recipient,
|
||||
data,
|
||||
lane,
|
||||
PacketType::Mix,
|
||||
max_retransmissions,
|
||||
)
|
||||
.await
|
||||
}
|
||||
InputMessage::Anonymous {
|
||||
recipient,
|
||||
data,
|
||||
reply_surbs,
|
||||
lane,
|
||||
max_retransmissions,
|
||||
} => {
|
||||
self.handle_repliable_message(recipient, data, reply_surbs, lane, PacketType::Mix)
|
||||
.await
|
||||
self.handle_repliable_message(
|
||||
recipient,
|
||||
data,
|
||||
reply_surbs,
|
||||
lane,
|
||||
PacketType::Mix,
|
||||
max_retransmissions,
|
||||
)
|
||||
.await
|
||||
}
|
||||
InputMessage::Reply {
|
||||
recipient_tag,
|
||||
data,
|
||||
lane,
|
||||
max_retransmissions,
|
||||
} => {
|
||||
self.handle_reply(recipient_tag, data, lane).await;
|
||||
self.handle_reply(recipient_tag, data, lane, max_retransmissions)
|
||||
.await;
|
||||
}
|
||||
InputMessage::Premade { msgs, lane } => self.handle_premade_packets(msgs, lane).await,
|
||||
InputMessage::MessageWrapper {
|
||||
@@ -145,25 +172,42 @@ where
|
||||
recipient,
|
||||
data,
|
||||
lane,
|
||||
max_retransmissions,
|
||||
} => {
|
||||
self.handle_plain_message(recipient, data, lane, packet_type)
|
||||
.await
|
||||
self.handle_plain_message(
|
||||
recipient,
|
||||
data,
|
||||
lane,
|
||||
packet_type,
|
||||
max_retransmissions,
|
||||
)
|
||||
.await
|
||||
}
|
||||
InputMessage::Anonymous {
|
||||
recipient,
|
||||
data,
|
||||
reply_surbs,
|
||||
lane,
|
||||
max_retransmissions,
|
||||
} => {
|
||||
self.handle_repliable_message(recipient, data, reply_surbs, lane, packet_type)
|
||||
.await
|
||||
self.handle_repliable_message(
|
||||
recipient,
|
||||
data,
|
||||
reply_surbs,
|
||||
lane,
|
||||
packet_type,
|
||||
max_retransmissions,
|
||||
)
|
||||
.await
|
||||
}
|
||||
InputMessage::Reply {
|
||||
recipient_tag,
|
||||
data,
|
||||
lane,
|
||||
max_retransmissions,
|
||||
} => {
|
||||
self.handle_reply(recipient_tag, data, lane).await;
|
||||
self.handle_reply(recipient_tag, data, lane, max_retransmissions)
|
||||
.await;
|
||||
}
|
||||
InputMessage::Premade { msgs, lane } => {
|
||||
self.handle_premade_packets(msgs, lane).await
|
||||
|
||||
@@ -72,6 +72,7 @@ pub struct PendingAcknowledgement {
|
||||
delay: SphinxDelay,
|
||||
destination: PacketDestination,
|
||||
retransmissions: u32,
|
||||
max_retransmissions: Option<u32>,
|
||||
}
|
||||
|
||||
impl PendingAcknowledgement {
|
||||
@@ -80,12 +81,14 @@ impl PendingAcknowledgement {
|
||||
message_chunk: Fragment,
|
||||
delay: SphinxDelay,
|
||||
recipient: Recipient,
|
||||
max_retransmissions: Option<u32>,
|
||||
) -> Self {
|
||||
PendingAcknowledgement {
|
||||
message_chunk,
|
||||
delay,
|
||||
destination: PacketDestination::KnownRecipient(recipient.into()),
|
||||
retransmissions: 0,
|
||||
max_retransmissions,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -94,6 +97,7 @@ impl PendingAcknowledgement {
|
||||
delay: SphinxDelay,
|
||||
recipient_tag: AnonymousSenderTag,
|
||||
extra_surb_request: bool,
|
||||
max_retransmissions: Option<u32>,
|
||||
) -> Self {
|
||||
PendingAcknowledgement {
|
||||
message_chunk,
|
||||
@@ -103,6 +107,7 @@ impl PendingAcknowledgement {
|
||||
extra_surb_request,
|
||||
},
|
||||
retransmissions: 0,
|
||||
max_retransmissions,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -118,6 +123,18 @@ impl PendingAcknowledgement {
|
||||
self.delay = new_delay;
|
||||
self.retransmissions += 1;
|
||||
}
|
||||
|
||||
pub(crate) fn reached_max_retransmissions(
|
||||
&self,
|
||||
global_max_retransmissions: Option<u32>,
|
||||
) -> bool {
|
||||
let reached_local_max = self
|
||||
.max_retransmissions
|
||||
.is_some_and(|limit| self.retransmissions >= limit);
|
||||
let reached_global_max =
|
||||
global_max_retransmissions.is_some_and(|limit| self.retransmissions >= limit);
|
||||
reached_local_max || reached_global_max
|
||||
}
|
||||
}
|
||||
|
||||
/// AcknowledgementControllerConnectors represents set of channels for communication with
|
||||
|
||||
+8
-10
@@ -79,17 +79,15 @@ where
|
||||
|
||||
let frag_id = timed_out_ack.message_chunk.fragment_identifier();
|
||||
|
||||
if let Some(limit) = self.maximum_retransmissions {
|
||||
if timed_out_ack.retransmissions >= limit {
|
||||
warn!("reached maximum number of allowed retransmissions for the packet");
|
||||
if let Err(err) = self
|
||||
.action_sender
|
||||
.unbounded_send(Action::new_remove(frag_id))
|
||||
{
|
||||
error!("Failed to send remove action to the controller: {err}");
|
||||
}
|
||||
return;
|
||||
if timed_out_ack.reached_max_retransmissions(self.maximum_retransmissions) {
|
||||
debug!("reached maximum number of allowed retransmissions for the packet");
|
||||
if let Err(err) = self
|
||||
.action_sender
|
||||
.unbounded_send(Action::new_remove(frag_id))
|
||||
{
|
||||
error!("Failed to send remove action to the controller: {err}");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
let maybe_prepared_fragment = match &timed_out_ack.destination {
|
||||
|
||||
@@ -6,6 +6,7 @@ use crate::client::real_messages_control::real_traffic_stream::{
|
||||
BatchRealMessageSender, RealMessage,
|
||||
};
|
||||
use crate::client::real_messages_control::{AckActionSender, Action};
|
||||
use crate::client::replies::reply_controller::MaxRetransmissions;
|
||||
use crate::client::replies::reply_storage::{ReceivedReplySurbsMap, SentReplyKeys, UsedSenderTags};
|
||||
use crate::client::topology_control::{TopologyAccessor, TopologyReadPermit};
|
||||
use log::{debug, error, info, trace, warn};
|
||||
@@ -142,6 +143,12 @@ impl Config {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub(crate) struct FragmentWithMaxRetransmissions {
|
||||
pub(crate) fragment: Fragment,
|
||||
pub(crate) max_retransmissions: MaxRetransmissions,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub(crate) struct MessageHandler<R> {
|
||||
config: Config,
|
||||
@@ -198,10 +205,10 @@ where
|
||||
trace!("we already had sender tag for {recipient}");
|
||||
existing
|
||||
} else {
|
||||
info!("creating new sender tag for {recipient}");
|
||||
debug!("creating new sender tag for {recipient}");
|
||||
let new_tag = AnonymousSenderTag::new_random(&mut self.rng);
|
||||
self.tag_storage.insert_new(recipient, new_tag);
|
||||
info!("we'll be using {new_tag} for all anonymous messages sent to {recipient}");
|
||||
info!("using {new_tag} for all anonymous messages sent to {recipient}");
|
||||
new_tag
|
||||
}
|
||||
}
|
||||
@@ -294,8 +301,14 @@ where
|
||||
Some(chunk.fragment_identifier()),
|
||||
);
|
||||
let delay = prepared_fragment.total_delay;
|
||||
let pending_ack =
|
||||
PendingAcknowledgement::new_anonymous(chunk, delay, target, is_extra_surb_request);
|
||||
let max_retransmissions = None;
|
||||
let pending_ack = PendingAcknowledgement::new_anonymous(
|
||||
chunk,
|
||||
delay,
|
||||
target,
|
||||
is_extra_surb_request,
|
||||
max_retransmissions,
|
||||
);
|
||||
|
||||
let lane = if is_extra_surb_request {
|
||||
TransmissionLane::ReplySurbRequest
|
||||
@@ -350,7 +363,7 @@ where
|
||||
pub(crate) async fn try_send_reply_chunks_on_lane(
|
||||
&mut self,
|
||||
target: AnonymousSenderTag,
|
||||
fragments: Vec<Fragment>,
|
||||
fragments: Vec<FragmentWithMaxRetransmissions>,
|
||||
reply_surbs: Vec<ReplySurb>,
|
||||
lane: TransmissionLane,
|
||||
) -> Result<(), SurbWrappedPreparationError> {
|
||||
@@ -367,12 +380,12 @@ where
|
||||
pub(crate) async fn try_send_reply_chunks(
|
||||
&mut self,
|
||||
target: AnonymousSenderTag,
|
||||
fragments: Vec<(TransmissionLane, Fragment)>,
|
||||
fragments: Vec<(TransmissionLane, FragmentWithMaxRetransmissions)>,
|
||||
reply_surbs: Vec<ReplySurb>,
|
||||
) -> Result<(), SurbWrappedPreparationError> {
|
||||
let prepared_fragments = self
|
||||
.prepare_reply_chunks_for_sending(
|
||||
fragments.iter().map(|(_, f)| f.clone()).collect(),
|
||||
fragments.iter().map(|(_, f)| f.fragment.clone()).collect(),
|
||||
reply_surbs,
|
||||
)
|
||||
.await?;
|
||||
@@ -382,12 +395,21 @@ where
|
||||
|
||||
for (raw, prepared) in fragments.into_iter().zip(prepared_fragments.into_iter()) {
|
||||
let lane = raw.0;
|
||||
let fragment = raw.1;
|
||||
let FragmentWithMaxRetransmissions {
|
||||
fragment,
|
||||
max_retransmissions,
|
||||
} = raw.1;
|
||||
|
||||
let real_message =
|
||||
RealMessage::new(prepared.mix_packet, Some(prepared.fragment_identifier));
|
||||
let delay = prepared.total_delay;
|
||||
let pending_ack = PendingAcknowledgement::new_anonymous(fragment, delay, target, false);
|
||||
let pending_ack = PendingAcknowledgement::new_anonymous(
|
||||
fragment,
|
||||
delay,
|
||||
target,
|
||||
false,
|
||||
max_retransmissions,
|
||||
);
|
||||
|
||||
let entry = to_forward.entry(lane).or_default();
|
||||
entry.push(real_message);
|
||||
@@ -416,10 +438,17 @@ where
|
||||
message: Vec<u8>,
|
||||
lane: TransmissionLane,
|
||||
packet_type: PacketType,
|
||||
max_retransmissions: Option<u32>,
|
||||
) -> Result<(), PreparationError> {
|
||||
let message = NymMessage::new_plain(message);
|
||||
self.try_split_and_send_non_reply_message(message, recipient, lane, packet_type)
|
||||
.await
|
||||
self.try_split_and_send_non_reply_message(
|
||||
message,
|
||||
recipient,
|
||||
lane,
|
||||
packet_type,
|
||||
max_retransmissions,
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
pub(crate) async fn try_split_and_send_non_reply_message(
|
||||
@@ -428,6 +457,7 @@ where
|
||||
recipient: Recipient,
|
||||
lane: TransmissionLane,
|
||||
packet_type: PacketType,
|
||||
max_retransmissions: Option<u32>,
|
||||
) -> Result<(), PreparationError> {
|
||||
debug!("Sending non-reply message with packet type {packet_type}");
|
||||
// TODO: I really dislike existence of this assertion, it implies code has to be re-organised
|
||||
@@ -467,7 +497,8 @@ where
|
||||
Some(fragment.fragment_identifier()),
|
||||
);
|
||||
let delay = prepared_fragment.total_delay;
|
||||
let pending_ack = PendingAcknowledgement::new_known(fragment, delay, recipient);
|
||||
let pending_ack =
|
||||
PendingAcknowledgement::new_known(fragment, delay, recipient, max_retransmissions);
|
||||
|
||||
real_messages.push(real_message);
|
||||
pending_acks.push(pending_ack);
|
||||
@@ -495,11 +526,15 @@ where
|
||||
reply_surbs,
|
||||
));
|
||||
|
||||
// When sending SURBs we want to retransmit
|
||||
let max_retransmissions = None;
|
||||
|
||||
self.try_split_and_send_non_reply_message(
|
||||
message,
|
||||
recipient,
|
||||
TransmissionLane::AdditionalReplySurbs,
|
||||
packet_type,
|
||||
max_retransmissions,
|
||||
)
|
||||
.await?;
|
||||
|
||||
@@ -516,6 +551,7 @@ where
|
||||
num_reply_surbs: u32,
|
||||
lane: TransmissionLane,
|
||||
packet_type: PacketType,
|
||||
max_retransmissions: Option<u32>,
|
||||
) -> Result<(), SurbWrappedPreparationError> {
|
||||
debug!("Sending message with reply SURBs with packet type {packet_type}");
|
||||
let sender_tag = self.get_or_create_sender_tag(&recipient);
|
||||
@@ -526,8 +562,14 @@ where
|
||||
let message =
|
||||
NymMessage::new_repliable(RepliableMessage::new_data(message, sender_tag, reply_surbs));
|
||||
|
||||
self.try_split_and_send_non_reply_message(message, recipient, lane, packet_type)
|
||||
.await?;
|
||||
self.try_split_and_send_non_reply_message(
|
||||
message,
|
||||
recipient,
|
||||
lane,
|
||||
packet_type,
|
||||
max_retransmissions,
|
||||
)
|
||||
.await?;
|
||||
|
||||
log::trace!("storing {} reply keys", reply_keys.len());
|
||||
self.reply_key_storage.insert_multiple(reply_keys);
|
||||
|
||||
@@ -153,7 +153,7 @@ impl RealMessagesController<OsRng> {
|
||||
let rng = OsRng;
|
||||
|
||||
// create channels for inter-task communication
|
||||
let (real_message_sender, real_message_receiver) = tokio::sync::mpsc::channel(1);
|
||||
let (real_message_sender, real_message_receiver) = tokio::sync::mpsc::channel(8);
|
||||
let (sent_notifier_tx, sent_notifier_rx) = mpsc::unbounded();
|
||||
let (ack_action_tx, ack_action_rx) = mpsc::unbounded();
|
||||
let ack_controller_connectors = AcknowledgementControllerConnectors::new(
|
||||
|
||||
@@ -23,6 +23,10 @@ use nym_statistics_common::clients::{packet_statistics::PacketStatisticsEvent, C
|
||||
use nym_task::TaskClient;
|
||||
use std::collections::HashSet;
|
||||
use std::sync::Arc;
|
||||
use std::time::{Duration, Instant};
|
||||
|
||||
// The interval at which we check for stale buffers
|
||||
const STALE_BUFFER_CHECK_INTERVAL: Duration = Duration::from_secs(10);
|
||||
|
||||
// Buffer Requests to say "hey, send any reconstructed messages to this channel"
|
||||
// or to say "hey, I'm going offline, don't send anything more to me. Just buffer them instead"
|
||||
@@ -48,6 +52,9 @@ struct ReceivedMessagesBufferInner<R: MessageReceiver> {
|
||||
recently_reconstructed: HashSet<i32>,
|
||||
|
||||
stats_tx: ClientStatsSender,
|
||||
|
||||
// Periodically check for stale buffers to clean up
|
||||
last_stale_check: Instant,
|
||||
}
|
||||
|
||||
impl<R: MessageReceiver> ReceivedMessagesBufferInner<R> {
|
||||
@@ -96,9 +103,10 @@ impl<R: MessageReceiver> ReceivedMessagesBufferInner<R> {
|
||||
}
|
||||
None
|
||||
}
|
||||
_ => unreachable!(
|
||||
"no other error kind should have been returned here! If so, it's a bug!"
|
||||
),
|
||||
_ => {
|
||||
error!("unexpected error occurred during message reconstruction: {err}");
|
||||
None
|
||||
}
|
||||
},
|
||||
Ok(reconstruction_result) => match reconstruction_result {
|
||||
Some((reconstructed_message, used_sets)) => {
|
||||
@@ -144,6 +152,16 @@ impl<R: MessageReceiver> ReceivedMessagesBufferInner<R> {
|
||||
|
||||
self.recover_from_fragment(fragment_data, raw_fragment_size)
|
||||
}
|
||||
|
||||
fn cleanup_stale_buffers(&mut self) {
|
||||
let now = Instant::now();
|
||||
if now - self.last_stale_check > STALE_BUFFER_CHECK_INTERVAL {
|
||||
self.last_stale_check = now;
|
||||
self.message_receiver
|
||||
.reconstructor()
|
||||
.cleanup_stale_buffers();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
@@ -172,6 +190,7 @@ impl<R: MessageReceiver> ReceivedMessagesBuffer<R> {
|
||||
message_sender: None,
|
||||
recently_reconstructed: HashSet::new(),
|
||||
stats_tx,
|
||||
last_stale_check: Instant::now(),
|
||||
})),
|
||||
reply_key_storage,
|
||||
reply_controller_sender,
|
||||
@@ -392,6 +411,11 @@ impl<R: MessageReceiver> ReceivedMessagesBuffer<R> {
|
||||
}
|
||||
}
|
||||
|
||||
// Cleanup stale buffers, if there are any fragments that simply never arrived.
|
||||
// We do this here as part of handling new received fragments so that we can keep the event
|
||||
// loop focused on processing new messages.
|
||||
inner_guard.cleanup_stale_buffers();
|
||||
|
||||
drop(inner_guard);
|
||||
|
||||
if !completed_messages.is_empty() {
|
||||
|
||||
@@ -2,7 +2,9 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::client::real_messages_control::acknowledgement_control::PendingAcknowledgement;
|
||||
use crate::client::real_messages_control::message_handler::{MessageHandler, PreparationError};
|
||||
use crate::client::real_messages_control::message_handler::{
|
||||
FragmentWithMaxRetransmissions, MessageHandler, PreparationError,
|
||||
};
|
||||
use crate::client::replies::reply_storage::CombinedReplyStorage;
|
||||
use futures::channel::oneshot;
|
||||
use futures::StreamExt;
|
||||
@@ -10,7 +12,7 @@ use log::{debug, error, info, trace, warn};
|
||||
use nym_sphinx::addressing::clients::Recipient;
|
||||
use nym_sphinx::anonymous_replies::requests::AnonymousSenderTag;
|
||||
use nym_sphinx::anonymous_replies::ReplySurb;
|
||||
use nym_sphinx::chunking::fragment::{Fragment, FragmentIdentifier};
|
||||
use nym_sphinx::chunking::fragment::FragmentIdentifier;
|
||||
use nym_task::connections::{ConnectionId, TransmissionLane};
|
||||
use nym_task::TaskClient;
|
||||
use rand::{CryptoRng, Rng};
|
||||
@@ -49,6 +51,8 @@ impl Config {
|
||||
// - replies to "give additional surbs" requests
|
||||
// - will reply to future heartbeats
|
||||
|
||||
pub type MaxRetransmissions = Option<u32>;
|
||||
|
||||
// TODO: this should be split into ingress and egress controllers
|
||||
// because currently its trying to perform two distinct jobs
|
||||
pub struct ReplyController<R> {
|
||||
@@ -59,7 +63,8 @@ pub struct ReplyController<R> {
|
||||
// of surbs required to send the message through
|
||||
// expected_reliability: f32,
|
||||
request_receiver: ReplyControllerReceiver,
|
||||
pending_replies: HashMap<AnonymousSenderTag, TransmissionBuffer<Fragment>>,
|
||||
pending_replies:
|
||||
HashMap<AnonymousSenderTag, TransmissionBuffer<FragmentWithMaxRetransmissions>>,
|
||||
|
||||
/// Retransmission packets that have already timed out and are waiting for additional reply SURBs
|
||||
/// so that they could be sent back to the network. Once we receive more SURBs, we should send them ASAP.
|
||||
@@ -96,7 +101,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
fn insert_pending_replies<I: IntoIterator<Item = Fragment>>(
|
||||
fn insert_pending_replies<I: IntoIterator<Item = FragmentWithMaxRetransmissions>>(
|
||||
&mut self,
|
||||
recipient: &AnonymousSenderTag,
|
||||
fragments: I,
|
||||
@@ -112,7 +117,7 @@ where
|
||||
fn re_insert_pending_replies(
|
||||
&mut self,
|
||||
recipient: &AnonymousSenderTag,
|
||||
fragments: Vec<(TransmissionLane, Fragment)>,
|
||||
fragments: Vec<(TransmissionLane, FragmentWithMaxRetransmissions)>,
|
||||
) {
|
||||
trace!("re-inserting pending replies for {recipient}");
|
||||
// the buffer should ALWAYS exist at this point, if it doesn't, it's a bug...
|
||||
@@ -205,6 +210,7 @@ where
|
||||
recipient_tag: AnonymousSenderTag,
|
||||
data: Vec<u8>,
|
||||
lane: TransmissionLane,
|
||||
max_retransmissions: Option<u32>,
|
||||
) {
|
||||
if !self
|
||||
.full_reply_storage
|
||||
@@ -242,7 +248,14 @@ where
|
||||
.get_reply_surbs(&recipient_tag, max_to_send);
|
||||
|
||||
if let Some(reply_surbs) = surbs {
|
||||
let to_send = fragments.drain(..max_to_send).collect::<Vec<_>>();
|
||||
let to_send = fragments
|
||||
.drain(..max_to_send)
|
||||
.map(|f| FragmentWithMaxRetransmissions {
|
||||
fragment: f,
|
||||
max_retransmissions,
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
if let Err(err) = self
|
||||
.message_handler
|
||||
.try_send_reply_chunks_on_lane(
|
||||
@@ -276,6 +289,13 @@ where
|
||||
"buffering {no_fragments} fragments for {recipient_tag}",
|
||||
no_fragments = fragments.len()
|
||||
);
|
||||
let fragments: Vec<_> = fragments
|
||||
.into_iter()
|
||||
.map(|fragment| FragmentWithMaxRetransmissions {
|
||||
fragment,
|
||||
max_retransmissions,
|
||||
})
|
||||
.collect();
|
||||
self.insert_pending_replies(&recipient_tag, fragments, lane);
|
||||
}
|
||||
|
||||
@@ -409,7 +429,7 @@ where
|
||||
&mut self,
|
||||
from: &AnonymousSenderTag,
|
||||
amount: usize,
|
||||
) -> Option<Vec<(TransmissionLane, Fragment)>> {
|
||||
) -> Option<Vec<(TransmissionLane, FragmentWithMaxRetransmissions)>> {
|
||||
// if possible, pop all pending replies, if not, pop only entries for which we'd have a reply surb
|
||||
let total = self.pending_replies.get(from)?.total_size();
|
||||
trace!("pending queue has {total} elements");
|
||||
@@ -689,7 +709,11 @@ where
|
||||
recipient,
|
||||
message,
|
||||
lane,
|
||||
} => self.handle_send_reply(recipient, message, lane).await,
|
||||
max_retransmissions,
|
||||
} => {
|
||||
self.handle_send_reply(recipient, message, lane, max_retransmissions)
|
||||
.await
|
||||
}
|
||||
ReplyControllerMessage::AdditionalSurbs {
|
||||
sender_tag,
|
||||
reply_surbs,
|
||||
|
||||
@@ -66,12 +66,14 @@ impl ReplyControllerSender {
|
||||
recipient: AnonymousSenderTag,
|
||||
message: Vec<u8>,
|
||||
lane: TransmissionLane,
|
||||
max_retransmissions: Option<u32>,
|
||||
) -> Result<(), ReplyControllerSenderError> {
|
||||
self.0
|
||||
.unbounded_send(ReplyControllerMessage::SendReply {
|
||||
recipient,
|
||||
message,
|
||||
lane,
|
||||
max_retransmissions,
|
||||
})
|
||||
.map_err(ReplyControllerSenderError::SendReply)
|
||||
}
|
||||
@@ -160,6 +162,7 @@ pub enum ReplyControllerMessage {
|
||||
recipient: AnonymousSenderTag,
|
||||
message: Vec<u8>,
|
||||
lane: TransmissionLane,
|
||||
max_retransmissions: Option<u32>,
|
||||
},
|
||||
|
||||
AdditionalSurbs {
|
||||
|
||||
@@ -11,6 +11,8 @@ use nym_topology::node::RoutingNode;
|
||||
use nym_validator_client::client::IdentityKeyRef;
|
||||
use nym_validator_client::UserAgent;
|
||||
use rand::{seq::SliceRandom, Rng};
|
||||
#[cfg(unix)]
|
||||
use std::os::fd::RawFd;
|
||||
use std::{sync::Arc, time::Duration};
|
||||
use tungstenite::Message;
|
||||
use url::Url;
|
||||
@@ -313,9 +315,15 @@ pub(super) async fn register_with_gateway(
|
||||
gateway_id: identity::PublicKey,
|
||||
gateway_listener: Url,
|
||||
our_identity: Arc<identity::KeyPair>,
|
||||
#[cfg(unix)] connection_fd_callback: Option<Arc<dyn Fn(RawFd) + Send + Sync>>,
|
||||
) -> Result<RegistrationResult, ClientCoreError> {
|
||||
let mut gateway_client =
|
||||
GatewayClient::new_init(gateway_listener, gateway_id, our_identity.clone());
|
||||
let mut gateway_client = GatewayClient::new_init(
|
||||
gateway_listener,
|
||||
gateway_id,
|
||||
our_identity.clone(),
|
||||
#[cfg(unix)]
|
||||
connection_fd_callback,
|
||||
);
|
||||
|
||||
gateway_client.establish_connection().await.map_err(|err| {
|
||||
log::warn!("Failed to establish connection with gateway!");
|
||||
|
||||
@@ -23,6 +23,8 @@ use nym_topology::node::RoutingNode;
|
||||
use rand::rngs::OsRng;
|
||||
use rand::{CryptoRng, RngCore};
|
||||
use serde::Serialize;
|
||||
#[cfg(unix)]
|
||||
use std::{os::fd::RawFd, sync::Arc};
|
||||
|
||||
pub mod helpers;
|
||||
pub mod types;
|
||||
@@ -53,6 +55,7 @@ async fn setup_new_gateway<K, D>(
|
||||
details_store: &D,
|
||||
selection_specification: GatewaySelectionSpecification,
|
||||
available_gateways: Vec<RoutingNode>,
|
||||
#[cfg(unix)] connection_fd_callback: Option<Arc<dyn Fn(RawFd) + Send + Sync>>,
|
||||
) -> Result<InitialisationResult, ClientCoreError>
|
||||
where
|
||||
K: KeyStore,
|
||||
@@ -108,9 +111,14 @@ where
|
||||
// if we're using a 'normal' gateway setup, do register
|
||||
let our_identity = client_keys.identity_keypair();
|
||||
|
||||
let registration =
|
||||
helpers::register_with_gateway(gateway_id, gateway_listener.clone(), our_identity)
|
||||
.await?;
|
||||
let registration = helpers::register_with_gateway(
|
||||
gateway_id,
|
||||
gateway_listener.clone(),
|
||||
our_identity,
|
||||
#[cfg(unix)]
|
||||
connection_fd_callback,
|
||||
)
|
||||
.await?;
|
||||
(
|
||||
GatewayDetails::new_remote(
|
||||
gateway_id,
|
||||
@@ -203,9 +211,19 @@ where
|
||||
GatewaySetup::New {
|
||||
specification,
|
||||
available_gateways,
|
||||
#[cfg(unix)]
|
||||
connection_fd_callback,
|
||||
} => {
|
||||
log::debug!("GatewaySetup::New with spec: {specification:?}");
|
||||
setup_new_gateway(key_store, details_store, specification, available_gateways).await
|
||||
setup_new_gateway(
|
||||
key_store,
|
||||
details_store,
|
||||
specification,
|
||||
available_gateways,
|
||||
#[cfg(unix)]
|
||||
connection_fd_callback,
|
||||
)
|
||||
.await
|
||||
}
|
||||
GatewaySetup::ReuseConnection {
|
||||
authenticated_ephemeral_client,
|
||||
|
||||
@@ -18,6 +18,8 @@ use nym_validator_client::client::IdentityKey;
|
||||
use nym_validator_client::nyxd::AccountId;
|
||||
use serde::Serialize;
|
||||
use std::fmt::{Debug, Display};
|
||||
#[cfg(unix)]
|
||||
use std::os::fd::RawFd;
|
||||
use std::sync::Arc;
|
||||
use time::OffsetDateTime;
|
||||
use url::Url;
|
||||
@@ -208,6 +210,10 @@ pub enum GatewaySetup {
|
||||
|
||||
// TODO: seems to be a bit inefficient to pass them by value
|
||||
available_gateways: Vec<RoutingNode>,
|
||||
|
||||
/// Callback useful for allowing initial connection to gateway
|
||||
#[cfg(unix)]
|
||||
connection_fd_callback: Option<Arc<dyn Fn(RawFd) + Send + Sync>>,
|
||||
},
|
||||
|
||||
ReuseConnection {
|
||||
@@ -231,6 +237,8 @@ impl Debug for GatewaySetup {
|
||||
GatewaySetup::New {
|
||||
specification,
|
||||
available_gateways,
|
||||
#[cfg(unix)]
|
||||
connection_fd_callback: _,
|
||||
} => f
|
||||
.debug_struct("GatewaySetup::New")
|
||||
.field("specification", specification)
|
||||
@@ -270,6 +278,8 @@ impl GatewaySetup {
|
||||
additional_data: None,
|
||||
},
|
||||
available_gateways: vec![],
|
||||
#[cfg(unix)]
|
||||
connection_fd_callback: None,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1065,6 +1065,7 @@ impl GatewayClient<InitOnly, EphemeralCredentialStorage> {
|
||||
gateway_listener: Url,
|
||||
gateway_identity: identity::PublicKey,
|
||||
local_identity: Arc<identity::KeyPair>,
|
||||
#[cfg(unix)] connection_fd_callback: Option<Arc<dyn Fn(RawFd) + Send + Sync>>,
|
||||
) -> Self {
|
||||
log::trace!("Initialising gateway client");
|
||||
use futures::channel::mpsc;
|
||||
@@ -1090,7 +1091,7 @@ impl GatewayClient<InitOnly, EphemeralCredentialStorage> {
|
||||
stats_reporter: ClientStatsSender::new(None, task_client.clone()),
|
||||
negotiated_protocol: None,
|
||||
#[cfg(unix)]
|
||||
connection_fd_callback: None,
|
||||
connection_fd_callback,
|
||||
task_client,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,10 +24,10 @@ use tracing::*;
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct Config {
|
||||
initial_reconnection_backoff: Duration,
|
||||
maximum_reconnection_backoff: Duration,
|
||||
initial_connection_timeout: Duration,
|
||||
maximum_connection_buffer_size: usize,
|
||||
pub initial_reconnection_backoff: Duration,
|
||||
pub maximum_reconnection_backoff: Duration,
|
||||
pub initial_connection_timeout: Duration,
|
||||
pub maximum_connection_buffer_size: usize,
|
||||
}
|
||||
|
||||
impl Config {
|
||||
@@ -50,7 +50,7 @@ pub trait SendWithoutResponse {
|
||||
// Without response in this context means we will not listen for anything we might get back (not
|
||||
// that we should get anything), including any possible io errors
|
||||
fn send_without_response(
|
||||
&mut self,
|
||||
&self,
|
||||
address: NymNodeRoutingAddress,
|
||||
packet: NymPacket,
|
||||
packet_type: PacketType,
|
||||
@@ -196,7 +196,7 @@ impl Client {
|
||||
}
|
||||
}
|
||||
|
||||
fn make_connection(&mut self, address: NymNodeRoutingAddress, pending_packet: FramedNymPacket) {
|
||||
fn make_connection(&self, address: NymNodeRoutingAddress, pending_packet: FramedNymPacket) {
|
||||
let (sender, receiver) = mpsc::channel(self.config.maximum_connection_buffer_size);
|
||||
|
||||
// this CAN'T fail because we just created the channel which has a non-zero capacity
|
||||
@@ -247,7 +247,7 @@ impl Client {
|
||||
|
||||
impl SendWithoutResponse for Client {
|
||||
fn send_without_response(
|
||||
&mut self,
|
||||
&self,
|
||||
address: NymNodeRoutingAddress,
|
||||
packet: NymPacket,
|
||||
packet_type: PacketType,
|
||||
|
||||
@@ -16,7 +16,6 @@ nym-coconut-dkg-common = { path = "../../cosmwasm-smart-contracts/coconut-dkg" }
|
||||
nym-contracts-common = { path = "../../cosmwasm-smart-contracts/contracts-common" }
|
||||
nym-mixnet-contract-common = { path = "../../cosmwasm-smart-contracts/mixnet-contract" }
|
||||
nym-vesting-contract-common = { path = "../../cosmwasm-smart-contracts/vesting-contract" }
|
||||
nym-coconut-bandwidth-contract-common = { path = "../../cosmwasm-smart-contracts/coconut-bandwidth-contract" }
|
||||
nym-ecash-contract-common = { path = "../../cosmwasm-smart-contracts/ecash-contract" }
|
||||
nym-multisig-contract-common = { path = "../../cosmwasm-smart-contracts/multisig-contract" }
|
||||
nym-group-contract-common = { path = "../../cosmwasm-smart-contracts/group-contract" }
|
||||
@@ -56,7 +55,7 @@ cw4 = { workspace = true }
|
||||
cw-controllers = { workspace = true }
|
||||
prost = { workspace = true, default-features = false }
|
||||
flate2 = { workspace = true }
|
||||
sha2 = { version = "0.9.5" }
|
||||
sha2 = { workspace = true }
|
||||
itertools = { workspace = true }
|
||||
zeroize = { workspace = true, features = ["zeroize_derive"] }
|
||||
cosmwasm-std = { workspace = true }
|
||||
|
||||
@@ -11,7 +11,9 @@ use crate::{
|
||||
use nym_api_requests::ecash::models::{
|
||||
AggregatedCoinIndicesSignatureResponse, AggregatedExpirationDateSignatureResponse,
|
||||
BatchRedeemTicketsBody, EcashBatchTicketRedemptionResponse, EcashTicketVerificationResponse,
|
||||
IssuedTicketbooksChallengeResponse, IssuedTicketbooksForResponse, VerifyEcashTicketBody,
|
||||
IssuedTicketbooksChallengeCommitmentRequest, IssuedTicketbooksChallengeCommitmentResponse,
|
||||
IssuedTicketbooksDataRequest, IssuedTicketbooksDataResponse, IssuedTicketbooksForCountResponse,
|
||||
IssuedTicketbooksForResponse, VerifyEcashTicketBody,
|
||||
};
|
||||
use nym_api_requests::ecash::{
|
||||
BlindSignRequestBody, BlindedSignatureResponse, PartialCoinIndicesSignatureResponse,
|
||||
@@ -25,15 +27,14 @@ use nym_api_requests::models::{
|
||||
use nym_api_requests::models::{LegacyDescribedGateway, MixNodeBondAnnotated};
|
||||
use nym_api_requests::nym_nodes::{NodesByAddressesResponse, SkimmedNode};
|
||||
use nym_coconut_dkg_common::types::EpochId;
|
||||
use nym_ecash_contract_common::deposit::DepositId;
|
||||
use nym_http_api_client::UserAgent;
|
||||
use nym_mixnet_contract_common::EpochRewardedSet;
|
||||
use nym_network_defaults::NymNetworkDetails;
|
||||
use std::net::IpAddr;
|
||||
use time::Date;
|
||||
use url::Url;
|
||||
|
||||
pub use crate::nym_api::NymApiClientExt;
|
||||
use nym_mixnet_contract_common::EpochRewardedSet;
|
||||
pub use nym_mixnet_contract_common::{
|
||||
mixnode::MixNodeDetails, GatewayBond, IdentityKey, IdentityKeyRef, NodeId, NymNodeDetails,
|
||||
};
|
||||
@@ -701,17 +702,33 @@ impl NymApiClient {
|
||||
Ok(self.nym_api.issued_ticketbooks_for(expiration_date).await?)
|
||||
}
|
||||
|
||||
pub async fn issued_ticketbooks_challenge(
|
||||
pub async fn issued_ticketbooks_for_count(
|
||||
&self,
|
||||
expiration_date: Date,
|
||||
deposits: Vec<DepositId>,
|
||||
) -> Result<IssuedTicketbooksChallengeResponse, ValidatorClientError> {
|
||||
) -> Result<IssuedTicketbooksForCountResponse, ValidatorClientError> {
|
||||
Ok(self
|
||||
.nym_api
|
||||
.issued_ticketbooks_challenge(expiration_date, deposits)
|
||||
.issued_ticketbooks_for_count(expiration_date)
|
||||
.await?)
|
||||
}
|
||||
|
||||
pub async fn issued_ticketbooks_challenge_commitment(
|
||||
&self,
|
||||
request: &IssuedTicketbooksChallengeCommitmentRequest,
|
||||
) -> Result<IssuedTicketbooksChallengeCommitmentResponse, ValidatorClientError> {
|
||||
Ok(self
|
||||
.nym_api
|
||||
.issued_ticketbooks_challenge_commitment(request)
|
||||
.await?)
|
||||
}
|
||||
|
||||
pub async fn issued_ticketbooks_data(
|
||||
&self,
|
||||
request: &IssuedTicketbooksDataRequest,
|
||||
) -> Result<IssuedTicketbooksDataResponse, ValidatorClientError> {
|
||||
Ok(self.nym_api.issued_ticketbooks_data(request).await?)
|
||||
}
|
||||
|
||||
pub async fn nodes_by_addresses(
|
||||
&self,
|
||||
addresses: Vec<IpAddr>,
|
||||
|
||||
@@ -7,7 +7,8 @@ use async_trait::async_trait;
|
||||
use nym_api_requests::ecash::models::{
|
||||
AggregatedCoinIndicesSignatureResponse, AggregatedExpirationDateSignatureResponse,
|
||||
BatchRedeemTicketsBody, EcashBatchTicketRedemptionResponse, EcashTicketVerificationResponse,
|
||||
IssuedTicketbooksChallengeRequest, IssuedTicketbooksChallengeResponse,
|
||||
IssuedTicketbooksChallengeCommitmentRequest, IssuedTicketbooksChallengeCommitmentResponse,
|
||||
IssuedTicketbooksDataRequest, IssuedTicketbooksDataResponse, IssuedTicketbooksForCountResponse,
|
||||
IssuedTicketbooksForResponse, VerifyEcashTicketBody,
|
||||
};
|
||||
use nym_api_requests::ecash::VerificationKeyResponse;
|
||||
@@ -36,10 +37,7 @@ pub use nym_api_requests::{
|
||||
nym_nodes::{CachedNodesResponse, SkimmedNode},
|
||||
NymNetworkDetailsResponse,
|
||||
};
|
||||
pub use nym_coconut_dkg_common::types::EpochId;
|
||||
use nym_contracts_common::IdentityKey;
|
||||
use nym_ecash_contract_common::deposit::DepositId;
|
||||
pub use nym_http_api_client::Client;
|
||||
use nym_http_api_client::{ApiClient, NO_PARAMS};
|
||||
use nym_mixnet_contract_common::mixnode::MixNodeDetails;
|
||||
use nym_mixnet_contract_common::{GatewayBond, IdentityKeyRef, NodeId, NymNodeDetails};
|
||||
@@ -48,6 +46,9 @@ use time::format_description::BorrowedFormatItem;
|
||||
use time::Date;
|
||||
use tracing::instrument;
|
||||
|
||||
pub use nym_coconut_dkg_common::types::EpochId;
|
||||
pub use nym_http_api_client::Client;
|
||||
|
||||
pub mod error;
|
||||
pub mod routes;
|
||||
|
||||
@@ -1012,22 +1013,52 @@ pub trait NymApiClientExt: ApiClient {
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
async fn issued_ticketbooks_challenge(
|
||||
async fn issued_ticketbooks_for_count(
|
||||
&self,
|
||||
expiration_date: Date,
|
||||
deposits: Vec<DepositId>,
|
||||
) -> Result<IssuedTicketbooksChallengeResponse, NymAPIError> {
|
||||
) -> Result<IssuedTicketbooksForCountResponse, NymAPIError> {
|
||||
self.get_json(
|
||||
&[
|
||||
routes::API_VERSION,
|
||||
routes::ECASH_ROUTES,
|
||||
routes::ECASH_ISSUED_TICKETBOOKS_FOR_COUNT,
|
||||
&expiration_date.to_string(),
|
||||
],
|
||||
NO_PARAMS,
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
async fn issued_ticketbooks_challenge_commitment(
|
||||
&self,
|
||||
request: &IssuedTicketbooksChallengeCommitmentRequest,
|
||||
) -> Result<IssuedTicketbooksChallengeCommitmentResponse, NymAPIError> {
|
||||
self.post_json(
|
||||
&[
|
||||
routes::API_VERSION,
|
||||
routes::ECASH_ROUTES,
|
||||
routes::ECASH_ISSUED_TICKETBOOKS_CHALLENGE,
|
||||
routes::ECASH_ISSUED_TICKETBOOKS_CHALLENGE_COMMITMENT,
|
||||
],
|
||||
NO_PARAMS,
|
||||
&IssuedTicketbooksChallengeRequest {
|
||||
expiration_date,
|
||||
deposits,
|
||||
},
|
||||
request,
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
async fn issued_ticketbooks_data(
|
||||
&self,
|
||||
request: &IssuedTicketbooksDataRequest,
|
||||
) -> Result<IssuedTicketbooksDataResponse, NymAPIError> {
|
||||
self.post_json(
|
||||
&[
|
||||
routes::API_VERSION,
|
||||
routes::ECASH_ROUTES,
|
||||
routes::ECASH_ISSUED_TICKETBOOKS_DATA,
|
||||
],
|
||||
NO_PARAMS,
|
||||
request,
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
@@ -26,7 +26,12 @@ pub mod ecash {
|
||||
pub const GLOBAL_COIN_INDICES_SIGNATURES: &str = "aggregated-coin-indices-signatures";
|
||||
pub const MASTER_VERIFICATION_KEY: &str = "master-verification-key";
|
||||
pub const ECASH_ISSUED_TICKETBOOKS_FOR: &str = "issued-ticketbooks-for";
|
||||
pub const ECASH_ISSUED_TICKETBOOKS_CHALLENGE: &str = "issued-ticketbooks-challenge";
|
||||
pub const ECASH_ISSUED_TICKETBOOKS_COUNT: &str = "issued-ticketbooks-count";
|
||||
pub const ECASH_ISSUED_TICKETBOOKS_FOR_COUNT: &str = "issued-ticketbooks-for-count";
|
||||
pub const ECASH_ISSUED_TICKETBOOKS_ON_COUNT: &str = "issued-ticketbooks-on-count";
|
||||
pub const ECASH_ISSUED_TICKETBOOKS_CHALLENGE_COMMITMENT: &str =
|
||||
"issued-ticketbooks-challenge-commitment";
|
||||
pub const ECASH_ISSUED_TICKETBOOKS_DATA: &str = "issued-ticketbooks-data";
|
||||
|
||||
pub const EXPIRATION_DATE_PARAM: &str = "expiration_date";
|
||||
pub const EPOCH_ID_PARAM: &str = "epoch_id";
|
||||
|
||||
@@ -48,7 +48,7 @@ impl Div<GasPrice> for &Coin {
|
||||
panic!("attempted to divide by zero!")
|
||||
};
|
||||
|
||||
let implicit_gas_limit = gas_price_inv * Uint128::new(self.amount);
|
||||
let implicit_gas_limit = Uint128::new(self.amount).mul_floor(gas_price_inv);
|
||||
if implicit_gas_limit.u128() >= u64::MAX as u128 {
|
||||
u64::MAX
|
||||
} else {
|
||||
@@ -169,13 +169,7 @@ impl CoinConverter for CosmosCoin {
|
||||
type Target = CosmWasmCoin;
|
||||
|
||||
fn convert_coin(&self) -> Self::Target {
|
||||
CosmWasmCoin::new(
|
||||
self.amount
|
||||
.to_string()
|
||||
.parse()
|
||||
.expect("cosmos coin had an invalid amount assigned"),
|
||||
self.denom.to_string(),
|
||||
)
|
||||
CosmWasmCoin::new(self.amount, self.denom.to_string())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+19
-28
@@ -7,10 +7,10 @@ use crate::nyxd::error::NyxdError;
|
||||
use crate::nyxd::{Coin, Fee, SigningCosmWasmClient};
|
||||
use crate::signing::signer::OfflineSigner;
|
||||
use async_trait::async_trait;
|
||||
use cosmwasm_std::{to_binary, CosmosMsg, WasmMsg};
|
||||
use cosmwasm_std::{CosmosMsg, Empty};
|
||||
use cw3::Vote;
|
||||
use cw4::{MemberChangedHookMsg, MemberDiff};
|
||||
use nym_coconut_bandwidth_contract_common::msg::ExecuteMsg as CoconutBandwidthExecuteMsg;
|
||||
use cw_utils::Expiration;
|
||||
use nym_multisig_contract_common::msg::ExecuteMsg as MultisigExecuteMsg;
|
||||
|
||||
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
|
||||
@@ -24,35 +24,23 @@ pub trait MultisigSigningClient: NymContractsProvider {
|
||||
funds: Vec<Coin>,
|
||||
) -> Result<ExecuteResult, NyxdError>;
|
||||
|
||||
async fn propose_release_funds(
|
||||
async fn propose(
|
||||
&self,
|
||||
title: String,
|
||||
blinded_serial_number: String,
|
||||
voucher_value: Coin,
|
||||
description: String,
|
||||
msgs: Vec<CosmosMsg<Empty>>,
|
||||
latest: Option<Expiration>,
|
||||
fee: Option<Fee>,
|
||||
) -> Result<ExecuteResult, NyxdError> {
|
||||
let ecash_contract_address = self
|
||||
.ecash_contract_address()
|
||||
.ok_or_else(|| NyxdError::unavailable_contract_address("coconut bandwidth contract"))?;
|
||||
|
||||
let release_funds_req = CoconutBandwidthExecuteMsg::ReleaseFunds {
|
||||
funds: voucher_value.into(),
|
||||
};
|
||||
let release_funds_msg = CosmosMsg::Wasm(WasmMsg::Execute {
|
||||
contract_addr: ecash_contract_address.to_string(),
|
||||
msg: to_binary(&release_funds_req)?,
|
||||
funds: vec![],
|
||||
});
|
||||
let req = MultisigExecuteMsg::Propose {
|
||||
title,
|
||||
description: blinded_serial_number,
|
||||
msgs: vec![release_funds_msg],
|
||||
latest: None,
|
||||
};
|
||||
self.execute_multisig_contract(
|
||||
fee,
|
||||
req,
|
||||
"Multisig::Propose::Execute::ReleaseFunds".to_string(),
|
||||
MultisigExecuteMsg::Propose {
|
||||
title,
|
||||
description,
|
||||
msgs,
|
||||
latest,
|
||||
},
|
||||
"Multisig::Propose".to_string(),
|
||||
vec![],
|
||||
)
|
||||
.await
|
||||
@@ -161,7 +149,7 @@ where
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::nyxd::contract_traits::tests::{mock_coin, IgnoreValue};
|
||||
use crate::nyxd::contract_traits::tests::IgnoreValue;
|
||||
|
||||
// it's enough that this compiles and clippy is happy about it
|
||||
#[allow(dead_code)]
|
||||
@@ -171,9 +159,12 @@ mod tests {
|
||||
) {
|
||||
match msg {
|
||||
MultisigExecuteMsg::Propose {
|
||||
title, description, ..
|
||||
title,
|
||||
description,
|
||||
msgs,
|
||||
latest,
|
||||
} => client
|
||||
.propose_release_funds(title, description, mock_coin(), None)
|
||||
.propose(title, description, msgs, latest, None)
|
||||
.ignore(),
|
||||
MultisigExecuteMsg::Vote { proposal_id, vote } => {
|
||||
client.vote(proposal_id, vote, None).ignore()
|
||||
|
||||
@@ -27,7 +27,7 @@ impl Mul<Gas> for &GasPrice {
|
||||
|
||||
fn mul(self, gas_limit: Gas) -> Self::Output {
|
||||
let limit_uint128 = Uint128::from(gas_limit);
|
||||
let mut amount = self.amount * limit_uint128;
|
||||
let mut amount = limit_uint128.mul_floor(self.amount);
|
||||
|
||||
let gas_price_numerator = self.amount.numerator();
|
||||
let gas_price_denominator = self.amount.denominator();
|
||||
@@ -35,7 +35,7 @@ impl Mul<Gas> for &GasPrice {
|
||||
// gas price is a fraction of the smallest fee token unit, so we must ensure that
|
||||
// for any multiplication, we have rounded up
|
||||
//
|
||||
// I don't really like the this solution as it has a theoretical chance of
|
||||
// I don't really like this solution as it has a theoretical chance of
|
||||
// overflowing (internally cosmwasm uses U256 to avoid that)
|
||||
// however, realistically that is impossible to happen as the resultant value
|
||||
// would have to be way higher than our token limit of 10^15 (1 billion of tokens * 1 million for denomination)
|
||||
|
||||
@@ -155,7 +155,7 @@ async fn fetch_delegation_data(
|
||||
match event.event.kind {
|
||||
// If a pending undelegate tx is found, remove it from delegation map
|
||||
PendingEpochEventKind::Undelegate { owner, node_id, .. } => {
|
||||
if owner == address.as_ref()
|
||||
if owner.as_str() == address.as_ref()
|
||||
&& existing_delegation_map.contains_key(&node_id.to_string())
|
||||
{
|
||||
existing_delegation_map.remove(&node_id.to_string());
|
||||
@@ -169,7 +169,7 @@ async fn fetch_delegation_data(
|
||||
amount,
|
||||
..
|
||||
} => {
|
||||
if owner == address.as_ref() {
|
||||
if owner.as_str() == address.as_ref() {
|
||||
let mut amount = Coin::from(amount);
|
||||
if let Some(pending_record) = pending_delegation_map.get(&node_id.to_string()) {
|
||||
amount.amount += pending_record.amount;
|
||||
|
||||
@@ -54,7 +54,7 @@ pub async fn create(args: Args, client: SigningClient, network_details: &NymNetw
|
||||
|
||||
let denom = network_details.chain_details.mix_denom.base.to_string();
|
||||
|
||||
let coin = Coin::new(args.amount.into(), &denom);
|
||||
let coin = Coin::new(args.amount, &denom);
|
||||
|
||||
let res = client
|
||||
.create_periodic_vesting_account(
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
[package]
|
||||
name = "nym-coconut-bandwidth-contract-common"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
license.workspace = true
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
cosmwasm-std = { workspace = true }
|
||||
cosmwasm-schema = { workspace = true }
|
||||
cw2 = { workspace = true, optional = true }
|
||||
nym-multisig-contract-common = { path = "../multisig-contract" }
|
||||
|
||||
[features]
|
||||
schema = ["cw2"]
|
||||
@@ -1,33 +0,0 @@
|
||||
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use cosmwasm_schema::cw_serde;
|
||||
|
||||
#[cw_serde]
|
||||
pub struct DepositData {
|
||||
deposit_info: String,
|
||||
identity_key: String,
|
||||
encryption_key: String,
|
||||
}
|
||||
|
||||
impl DepositData {
|
||||
pub fn new(deposit_info: String, identity_key: String, encryption_key: String) -> Self {
|
||||
DepositData {
|
||||
deposit_info,
|
||||
identity_key,
|
||||
encryption_key,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn deposit_info(&self) -> &str {
|
||||
&self.deposit_info
|
||||
}
|
||||
|
||||
pub fn identity_key(&self) -> &str {
|
||||
&self.identity_key
|
||||
}
|
||||
|
||||
pub fn encryption_key(&self) -> &str {
|
||||
&self.encryption_key
|
||||
}
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
pub const BANDWIDTH_PROPOSAL_ID: &str = "proposal_id";
|
||||
@@ -1,11 +0,0 @@
|
||||
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// event types
|
||||
pub const DEPOSITED_FUNDS_EVENT_TYPE: &str = "deposited-funds";
|
||||
|
||||
// attributes that are used in multiple places
|
||||
pub const DEPOSIT_VALUE: &str = "deposit-value";
|
||||
pub const DEPOSIT_INFO: &str = "deposit-info";
|
||||
pub const DEPOSIT_IDENTITY_KEY: &str = "deposit-identity-key";
|
||||
pub const DEPOSIT_ENCRYPTION_KEY: &str = "deposit-encryption-key";
|
||||
@@ -1,5 +0,0 @@
|
||||
pub mod deposit;
|
||||
pub mod event_attributes;
|
||||
pub mod events;
|
||||
pub mod msg;
|
||||
pub mod spend_credential;
|
||||
@@ -1,41 +0,0 @@
|
||||
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::{deposit::DepositData, spend_credential::SpendCredentialData};
|
||||
use cosmwasm_schema::cw_serde;
|
||||
use cosmwasm_std::Coin;
|
||||
|
||||
#[cfg(feature = "schema")]
|
||||
use crate::spend_credential::{PagedSpendCredentialResponse, SpendCredentialResponse};
|
||||
#[cfg(feature = "schema")]
|
||||
use cosmwasm_schema::QueryResponses;
|
||||
|
||||
#[cw_serde]
|
||||
pub struct InstantiateMsg {
|
||||
pub multisig_addr: String,
|
||||
pub pool_addr: String,
|
||||
pub mix_denom: String,
|
||||
}
|
||||
|
||||
#[cw_serde]
|
||||
pub enum ExecuteMsg {
|
||||
DepositFunds { data: DepositData },
|
||||
SpendCredential { data: SpendCredentialData },
|
||||
ReleaseFunds { funds: Coin },
|
||||
}
|
||||
|
||||
#[cw_serde]
|
||||
#[cfg_attr(feature = "schema", derive(QueryResponses))]
|
||||
pub enum QueryMsg {
|
||||
#[cfg_attr(feature = "schema", returns(SpendCredentialResponse))]
|
||||
GetSpentCredential { blinded_serial_number: String },
|
||||
|
||||
#[cfg_attr(feature = "schema", returns(PagedSpendCredentialResponse))]
|
||||
GetAllSpentCredentials {
|
||||
limit: Option<u32>,
|
||||
start_after: Option<String>,
|
||||
},
|
||||
}
|
||||
|
||||
#[cw_serde]
|
||||
pub struct MigrateMsg {}
|
||||
@@ -1,152 +0,0 @@
|
||||
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use cosmwasm_schema::cw_serde;
|
||||
use cosmwasm_std::{from_binary, to_binary, Addr, Coin, CosmosMsg, StdResult, WasmMsg};
|
||||
use nym_multisig_contract_common::msg::ExecuteMsg as MultisigExecuteMsg;
|
||||
|
||||
use crate::msg::ExecuteMsg;
|
||||
|
||||
#[cw_serde]
|
||||
pub struct SpendCredentialData {
|
||||
funds: Coin,
|
||||
blinded_serial_number: String,
|
||||
gateway_cosmos_address: String,
|
||||
}
|
||||
|
||||
impl SpendCredentialData {
|
||||
pub fn new(funds: Coin, blinded_serial_number: String, gateway_cosmos_address: String) -> Self {
|
||||
SpendCredentialData {
|
||||
funds,
|
||||
blinded_serial_number,
|
||||
gateway_cosmos_address,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn funds(&self) -> &Coin {
|
||||
&self.funds
|
||||
}
|
||||
|
||||
pub fn blinded_serial_number(&self) -> &str {
|
||||
&self.blinded_serial_number
|
||||
}
|
||||
|
||||
pub fn gateway_cosmos_address(&self) -> &str {
|
||||
&self.gateway_cosmos_address
|
||||
}
|
||||
}
|
||||
|
||||
#[cw_serde]
|
||||
#[derive(Copy)]
|
||||
pub enum SpendCredentialStatus {
|
||||
#[serde(alias = "InProgress")]
|
||||
InProgress,
|
||||
#[serde(alias = "Spent")]
|
||||
Spent,
|
||||
}
|
||||
|
||||
#[cw_serde]
|
||||
pub struct SpendCredential {
|
||||
funds: Coin,
|
||||
blinded_serial_number: String,
|
||||
gateway_cosmos_address: Addr,
|
||||
status: SpendCredentialStatus,
|
||||
}
|
||||
|
||||
impl SpendCredential {
|
||||
pub fn new(funds: Coin, blinded_serial_number: String, gateway_cosmos_address: Addr) -> Self {
|
||||
SpendCredential {
|
||||
funds,
|
||||
blinded_serial_number,
|
||||
gateway_cosmos_address,
|
||||
status: SpendCredentialStatus::InProgress,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn blinded_serial_number(&self) -> &str {
|
||||
&self.blinded_serial_number
|
||||
}
|
||||
|
||||
pub fn status(&self) -> SpendCredentialStatus {
|
||||
self.status
|
||||
}
|
||||
|
||||
pub fn mark_as_spent(&mut self) {
|
||||
self.status = SpendCredentialStatus::Spent;
|
||||
}
|
||||
}
|
||||
|
||||
#[cw_serde]
|
||||
pub struct PagedSpendCredentialResponse {
|
||||
pub spend_credentials: Vec<SpendCredential>,
|
||||
pub per_page: usize,
|
||||
|
||||
/// Field indicating paging information for the following queries if the caller wishes to get further entries.
|
||||
pub start_next_after: Option<String>,
|
||||
}
|
||||
|
||||
impl PagedSpendCredentialResponse {
|
||||
pub fn new(
|
||||
spend_credentials: Vec<SpendCredential>,
|
||||
per_page: usize,
|
||||
start_next_after: Option<String>,
|
||||
) -> Self {
|
||||
PagedSpendCredentialResponse {
|
||||
spend_credentials,
|
||||
per_page,
|
||||
start_next_after,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cw_serde]
|
||||
pub struct SpendCredentialResponse {
|
||||
pub spend_credential: Option<SpendCredential>,
|
||||
}
|
||||
|
||||
impl SpendCredentialResponse {
|
||||
pub fn new(spend_credential: Option<SpendCredential>) -> Self {
|
||||
SpendCredentialResponse { spend_credential }
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_cosmos_msg(
|
||||
funds: Coin,
|
||||
blinded_serial_number: String,
|
||||
coconut_bandwidth_addr: String,
|
||||
multisig_addr: String,
|
||||
) -> StdResult<CosmosMsg> {
|
||||
let release_funds_req = ExecuteMsg::ReleaseFunds { funds };
|
||||
let release_funds_msg = CosmosMsg::Wasm(WasmMsg::Execute {
|
||||
contract_addr: coconut_bandwidth_addr,
|
||||
msg: to_binary(&release_funds_req)?,
|
||||
funds: vec![],
|
||||
});
|
||||
let req = MultisigExecuteMsg::Propose {
|
||||
title: String::from("Release funds, as ordered by Coconut Bandwidth Contract"),
|
||||
description: blinded_serial_number,
|
||||
msgs: vec![release_funds_msg],
|
||||
latest: None,
|
||||
};
|
||||
let msg = CosmosMsg::Wasm(WasmMsg::Execute {
|
||||
contract_addr: multisig_addr,
|
||||
msg: to_binary(&req)?,
|
||||
funds: vec![],
|
||||
});
|
||||
|
||||
Ok(msg)
|
||||
}
|
||||
|
||||
pub fn funds_from_cosmos_msgs(msgs: Vec<CosmosMsg>) -> Option<Coin> {
|
||||
if let Some(CosmosMsg::Wasm(WasmMsg::Execute {
|
||||
contract_addr: _,
|
||||
msg,
|
||||
funds: _,
|
||||
})) = msgs.first()
|
||||
{
|
||||
if let Ok(ExecuteMsg::ReleaseFunds { funds }) = from_binary::<ExecuteMsg>(msg) {
|
||||
return Some(funds);
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
@@ -4,7 +4,7 @@
|
||||
use crate::msg::ExecuteMsg;
|
||||
use crate::types::{EpochId, NodeIndex};
|
||||
use cosmwasm_schema::cw_serde;
|
||||
use cosmwasm_std::{from_binary, to_binary, Addr, CosmosMsg, StdResult, Timestamp, WasmMsg};
|
||||
use cosmwasm_std::{from_json, to_json_binary, Addr, CosmosMsg, StdResult, Timestamp, WasmMsg};
|
||||
use cw_utils::Expiration;
|
||||
use nym_multisig_contract_common::msg::ExecuteMsg as MultisigExecuteMsg;
|
||||
|
||||
@@ -49,7 +49,7 @@ pub fn to_cosmos_msg(
|
||||
};
|
||||
let verify_vk_share_msg = CosmosMsg::Wasm(WasmMsg::Execute {
|
||||
contract_addr: coconut_dkg_addr,
|
||||
msg: to_binary(&verify_vk_share_req)?,
|
||||
msg: to_json_binary(&verify_vk_share_req)?,
|
||||
funds: vec![],
|
||||
});
|
||||
let req = MultisigExecuteMsg::Propose {
|
||||
@@ -60,7 +60,7 @@ pub fn to_cosmos_msg(
|
||||
};
|
||||
let msg = CosmosMsg::Wasm(WasmMsg::Execute {
|
||||
contract_addr: multisig_addr,
|
||||
msg: to_binary(&req)?,
|
||||
msg: to_json_binary(&req)?,
|
||||
funds: vec![],
|
||||
});
|
||||
|
||||
@@ -82,7 +82,7 @@ pub fn owner_from_cosmos_msgs(msgs: &[CosmosMsg]) -> Option<String> {
|
||||
})) = msgs.first()
|
||||
{
|
||||
if let Ok(ExecuteMsg::VerifyVerificationKeyShare { owner, .. }) =
|
||||
from_binary::<ExecuteMsg>(msg)
|
||||
from_json::<ExecuteMsg>(msg)
|
||||
{
|
||||
return Some(owner);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use cosmwasm_std::{from_slice, to_vec, Addr, Coin, MessageInfo, StdResult};
|
||||
use cosmwasm_std::{from_json, to_json_vec, Addr, Coin, MessageInfo, StdResult};
|
||||
use schemars::JsonSchema;
|
||||
use serde::de::DeserializeOwned;
|
||||
use serde::{de, Deserialize, Deserializer, Serialize, Serializer};
|
||||
@@ -164,7 +164,7 @@ where
|
||||
where
|
||||
T: Serialize,
|
||||
{
|
||||
to_vec(self)
|
||||
to_json_vec(self)
|
||||
}
|
||||
|
||||
pub fn to_sha256_plaintext_digest(&self) -> StdResult<Vec<u8>>
|
||||
@@ -195,7 +195,7 @@ where
|
||||
where
|
||||
T: DeserializeOwned,
|
||||
{
|
||||
from_slice(bytes)
|
||||
from_json(bytes)
|
||||
}
|
||||
|
||||
pub fn try_from_string(raw: &str) -> StdResult<SignableMessage<T>>
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use cosmwasm_schema::cw_serde;
|
||||
use cosmwasm_std::Decimal;
|
||||
use cosmwasm_std::OverflowError;
|
||||
use cosmwasm_std::Uint128;
|
||||
use cosmwasm_std::{Decimal, Fraction};
|
||||
use serde::de::Error;
|
||||
use serde::{Deserialize, Deserializer};
|
||||
use std::fmt::{self, Display, Formatter};
|
||||
@@ -17,7 +17,7 @@ pub type IdentityKey = String;
|
||||
pub type IdentityKeyRef<'a> = &'a str;
|
||||
|
||||
pub fn truncate_decimal(amount: Decimal) -> Uint128 {
|
||||
amount * Uint128::new(1)
|
||||
Uint128::new(1).mul_floor(amount)
|
||||
}
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
@@ -113,11 +113,17 @@ impl Mul<Percent> for Decimal {
|
||||
}
|
||||
}
|
||||
|
||||
impl Mul<Uint128> for Percent {
|
||||
type Output = Uint128;
|
||||
impl Fraction<Uint128> for Percent {
|
||||
fn numerator(&self) -> Uint128 {
|
||||
self.0.numerator()
|
||||
}
|
||||
|
||||
fn mul(self, rhs: Uint128) -> Self::Output {
|
||||
self.0 * rhs
|
||||
fn denominator(&self) -> Uint128 {
|
||||
self.0.denominator()
|
||||
}
|
||||
|
||||
fn inv(&self) -> Option<Self> {
|
||||
Percent::new(self.0.inv()?).ok()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
[package]
|
||||
name = "easy-addr"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
publish = false
|
||||
license.workspace = true
|
||||
|
||||
[lib]
|
||||
proc-macro = true
|
||||
|
||||
[dependencies]
|
||||
cosmwasm-std = { workspace = true }
|
||||
quote = { workspace = true }
|
||||
syn = { workspace = true, features = ["full", "printing", "extra-traits"] }
|
||||
@@ -0,0 +1,12 @@
|
||||
use cosmwasm_std::testing::MockApi;
|
||||
|
||||
use proc_macro::TokenStream;
|
||||
use quote::quote;
|
||||
use syn::parse_macro_input;
|
||||
|
||||
#[proc_macro]
|
||||
pub fn addr(input: TokenStream) -> TokenStream {
|
||||
let input = parse_macro_input!(input as syn::LitStr).value();
|
||||
let addr = MockApi::default().addr_make(input.as_str()).to_string();
|
||||
TokenStream::from(quote! {#addr})
|
||||
}
|
||||
@@ -241,10 +241,10 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn gateway_bond_partial_ord() {
|
||||
let _150foos = Coin::new(150, "foo");
|
||||
let _140foos = Coin::new(140, "foo");
|
||||
let _50foos = Coin::new(50, "foo");
|
||||
let _0foos = Coin::new(0, "foo");
|
||||
let _150foos = Coin::new(150u32, "foo");
|
||||
let _140foos = Coin::new(140u32, "foo");
|
||||
let _50foos = Coin::new(50u32, "foo");
|
||||
let _0foos = Coin::new(0u32, "foo");
|
||||
|
||||
let gate1 = GatewayBond {
|
||||
pledge_amount: _150foos.clone(),
|
||||
|
||||
@@ -34,8 +34,10 @@ where
|
||||
{
|
||||
fn into_base_decimal(self) -> StdResult<Decimal> {
|
||||
let atomics = self.into();
|
||||
Decimal::from_atomics(atomics, 0).map_err(|_| StdError::GenericErr {
|
||||
msg: format!("Decimal range exceeded for {atomics} with 0 decimal places."),
|
||||
Decimal::from_atomics(atomics, 0).map_err(|_| {
|
||||
StdError::generic_err(format!(
|
||||
"Decimal range exceeded for {atomics} with 0 decimal places."
|
||||
))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,6 +77,8 @@ impl<'a> PrimaryKey<'a> for Role {
|
||||
impl KeyDeserialize for Role {
|
||||
type Output = Role;
|
||||
|
||||
const KEY_ELEMS: u16 = 1;
|
||||
|
||||
fn from_vec(value: Vec<u8>) -> StdResult<Self::Output> {
|
||||
let u8_key: <u8 as KeyDeserialize>::Output = <u8 as KeyDeserialize>::from_vec(value)?;
|
||||
Role::try_from(u8_key).map_err(|err| StdError::generic_err(err.to_string()))
|
||||
|
||||
@@ -242,7 +242,7 @@ mod tests {
|
||||
#[allow(clippy::unwrap_used)]
|
||||
fn base_simulator(initial_pledge: u128) -> Simulator {
|
||||
let profit_margin = Percent::from_percentage_value(10).unwrap();
|
||||
let interval_operating_cost = Coin::new(40_000_000, "unym");
|
||||
let interval_operating_cost = Coin::new(40_000_000u64, "unym");
|
||||
let epochs_in_interval = 720u32;
|
||||
let interval_pool_emission = Percent::from_percentage_value(2).unwrap();
|
||||
|
||||
@@ -347,7 +347,7 @@ mod tests {
|
||||
fn single_delegation_at_genesis() {
|
||||
let mut simulator = base_simulator(10000_000000);
|
||||
simulator
|
||||
.delegate("alice", Coin::new(18000_000000, "unym"), 0)
|
||||
.delegate("alice", Coin::new(18000_000000u64, "unym"), 0)
|
||||
.unwrap();
|
||||
|
||||
let node_params = NodeRewardingParameters::new(
|
||||
@@ -393,7 +393,7 @@ mod tests {
|
||||
compare_decimals(rewards1.operator, expected_operator1, None);
|
||||
|
||||
simulator
|
||||
.delegate("alice", Coin::new(18000_000000, "unym"), 0)
|
||||
.delegate("alice", Coin::new(18000_000000u64, "unym"), 0)
|
||||
.unwrap();
|
||||
|
||||
let rewards2 = simulator.simulate_epoch_single_node(node_params).unwrap();
|
||||
@@ -439,10 +439,10 @@ mod tests {
|
||||
// add 2 delegations at genesis (because it makes things easier and as shown with previous tests
|
||||
// delegating at different times still work)
|
||||
simulator
|
||||
.delegate("alice", Coin::new(18000_000000, "unym"), 0)
|
||||
.delegate("alice", Coin::new(18000_000000u64, "unym"), 0)
|
||||
.unwrap();
|
||||
simulator
|
||||
.delegate("bob", Coin::new(4000_000000, "unym"), 0)
|
||||
.delegate("bob", Coin::new(4000_000000u64, "unym"), 0)
|
||||
.unwrap();
|
||||
|
||||
// "normal", sanity check rewarding
|
||||
@@ -484,10 +484,10 @@ mod tests {
|
||||
// add 2 delegations at genesis (because it makes things easier and as shown with previous tests
|
||||
// delegating at different times still work)
|
||||
simulator
|
||||
.delegate("alice", Coin::new(18000_000000, "unym"), 0)
|
||||
.delegate("alice", Coin::new(18000_000000u64, "unym"), 0)
|
||||
.unwrap();
|
||||
simulator
|
||||
.delegate("bob", Coin::new(4000_000000, "unym"), 0)
|
||||
.delegate("bob", Coin::new(4000_000000u64, "unym"), 0)
|
||||
.unwrap();
|
||||
|
||||
// "normal", sanity check rewarding
|
||||
@@ -553,12 +553,12 @@ mod tests {
|
||||
for epoch in 0..720 {
|
||||
if epoch == 0 {
|
||||
simulator
|
||||
.delegate("a", Coin::new(18000_000000, "unym"), 0)
|
||||
.delegate("a", Coin::new(18000_000000u64, "unym"), 0)
|
||||
.unwrap()
|
||||
}
|
||||
if epoch == 42 {
|
||||
simulator
|
||||
.delegate("b", Coin::new(2000_000000, "unym"), 0)
|
||||
.delegate("b", Coin::new(2000_000000u64, "unym"), 0)
|
||||
.unwrap()
|
||||
}
|
||||
if epoch == 89 {
|
||||
@@ -566,7 +566,7 @@ mod tests {
|
||||
}
|
||||
if epoch == 123 {
|
||||
simulator
|
||||
.delegate("c", Coin::new(6666_000000, "unym"), 0)
|
||||
.delegate("c", Coin::new(6666_000000u64, "unym"), 0)
|
||||
.unwrap()
|
||||
}
|
||||
if epoch == 167 {
|
||||
@@ -574,7 +574,7 @@ mod tests {
|
||||
}
|
||||
if epoch == 245 {
|
||||
simulator
|
||||
.delegate("d", Coin::new(2050_000000, "unym"), 0)
|
||||
.delegate("d", Coin::new(2050_000000u64, "unym"), 0)
|
||||
.unwrap()
|
||||
}
|
||||
if epoch == 264 {
|
||||
@@ -597,7 +597,7 @@ mod tests {
|
||||
}
|
||||
if epoch == 545 {
|
||||
simulator
|
||||
.delegate("e", Coin::new(5000_000000, "unym"), 0)
|
||||
.delegate("e", Coin::new(5000_000000u64, "unym"), 0)
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
@@ -666,132 +666,132 @@ mod tests {
|
||||
|
||||
let n0 = simulator
|
||||
.bond(
|
||||
Coin::new(11_000_000_000000, "unym"),
|
||||
Coin::new(11_000_000_000000u64, "unym"),
|
||||
NodeCostParams {
|
||||
profit_margin_percent: Percent::from_percentage_value(10).unwrap(),
|
||||
interval_operating_cost: Coin::new(40_000_000, "unym"),
|
||||
interval_operating_cost: Coin::new(40_000_000u64, "unym"),
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
simulator
|
||||
.delegate("delegator", Coin::new(1_000_000_000000, "unym"), n0)
|
||||
.delegate("delegator", Coin::new(1_000_000_000000u64, "unym"), n0)
|
||||
.unwrap();
|
||||
|
||||
let n1 = simulator
|
||||
.bond(
|
||||
Coin::new(1_000_000_000000, "unym"),
|
||||
Coin::new(1_000_000_000000u64, "unym"),
|
||||
NodeCostParams {
|
||||
profit_margin_percent: Percent::from_percentage_value(10).unwrap(),
|
||||
interval_operating_cost: Coin::new(40_000_000, "unym"),
|
||||
interval_operating_cost: Coin::new(40_000_000u64, "unym"),
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
simulator
|
||||
.delegate("delegator", Coin::new(11_000_000_000000, "unym"), n1)
|
||||
.delegate("delegator", Coin::new(11_000_000_000000u64, "unym"), n1)
|
||||
.unwrap();
|
||||
|
||||
let n2 = simulator
|
||||
.bond(
|
||||
Coin::new(1_000_000_000000, "unym"),
|
||||
Coin::new(1_000_000_000000u64, "unym"),
|
||||
NodeCostParams {
|
||||
profit_margin_percent: Percent::from_percentage_value(10).unwrap(),
|
||||
interval_operating_cost: Coin::new(40_000_000, "unym"),
|
||||
interval_operating_cost: Coin::new(40_000_000u64, "unym"),
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
simulator
|
||||
.delegate("delegator", Coin::new(9_000_000_000000, "unym"), n2)
|
||||
.delegate("delegator", Coin::new(9_000_000_000000u64, "unym"), n2)
|
||||
.unwrap();
|
||||
|
||||
let n3 = simulator
|
||||
.bond(
|
||||
Coin::new(1_000_000_000000, "unym"),
|
||||
Coin::new(1_000_000_000000u64, "unym"),
|
||||
NodeCostParams {
|
||||
profit_margin_percent: Percent::from_percentage_value(0).unwrap(),
|
||||
interval_operating_cost: Coin::new(500_000_000, "unym"),
|
||||
interval_operating_cost: Coin::new(500_000_000u64, "unym"),
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
simulator
|
||||
.delegate("delegator", Coin::new(7_000_000_000000, "unym"), n3)
|
||||
.delegate("delegator", Coin::new(7_000_000_000000u64, "unym"), n3)
|
||||
.unwrap();
|
||||
|
||||
let n4 = simulator
|
||||
.bond(
|
||||
Coin::new(1000_000000, "unym"),
|
||||
Coin::new(1000_000000u64, "unym"),
|
||||
NodeCostParams {
|
||||
profit_margin_percent: Percent::from_percentage_value(10).unwrap(),
|
||||
interval_operating_cost: Coin::new(40_000_000, "unym"),
|
||||
interval_operating_cost: Coin::new(40_000_000u64, "unym"),
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
simulator
|
||||
.delegate("delegator", Coin::new(7_999_000_000000, "unym"), n4)
|
||||
.delegate("delegator", Coin::new(7_999_000_000000u64, "unym"), n4)
|
||||
.unwrap();
|
||||
|
||||
let n5 = simulator
|
||||
.bond(
|
||||
Coin::new(1_000_000_000000, "unym"),
|
||||
Coin::new(1_000_000_000000u64, "unym"),
|
||||
NodeCostParams {
|
||||
profit_margin_percent: Percent::from_percentage_value(10).unwrap(),
|
||||
interval_operating_cost: Coin::new(40_000_000, "unym"),
|
||||
interval_operating_cost: Coin::new(40_000_000u64, "unym"),
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
simulator
|
||||
.delegate("delegator", Coin::new(7_000_000_000000, "unym"), n5)
|
||||
.delegate("delegator", Coin::new(7_000_000_000000u64, "unym"), n5)
|
||||
.unwrap();
|
||||
|
||||
let n6 = simulator
|
||||
.bond(
|
||||
Coin::new(11_000_000_000000, "unym"),
|
||||
Coin::new(11_000_000_000000u64, "unym"),
|
||||
NodeCostParams {
|
||||
profit_margin_percent: Percent::from_percentage_value(10).unwrap(),
|
||||
interval_operating_cost: Coin::new(40_000_000, "unym"),
|
||||
interval_operating_cost: Coin::new(40_000_000u64, "unym"),
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
simulator
|
||||
.delegate("delegator", Coin::new(1_000_000_000000, "unym"), n6)
|
||||
.delegate("delegator", Coin::new(1_000_000_000000u64, "unym"), n6)
|
||||
.unwrap();
|
||||
|
||||
let n7 = simulator
|
||||
.bond(
|
||||
Coin::new(1_000_000_000000, "unym"),
|
||||
Coin::new(1_000_000_000000u64, "unym"),
|
||||
NodeCostParams {
|
||||
profit_margin_percent: Percent::from_percentage_value(10).unwrap(),
|
||||
interval_operating_cost: Coin::new(40_000_000, "unym"),
|
||||
interval_operating_cost: Coin::new(40_000_000u64, "unym"),
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
simulator
|
||||
.delegate("delegator", Coin::new(9_000_000_000000, "unym"), n7)
|
||||
.delegate("delegator", Coin::new(9_000_000_000000u64, "unym"), n7)
|
||||
.unwrap();
|
||||
|
||||
let n8 = simulator
|
||||
.bond(
|
||||
Coin::new(1_000_000_000000, "unym"),
|
||||
Coin::new(1_000_000_000000u64, "unym"),
|
||||
NodeCostParams {
|
||||
profit_margin_percent: Percent::from_percentage_value(0).unwrap(),
|
||||
interval_operating_cost: Coin::new(500_000_000, "unym"),
|
||||
interval_operating_cost: Coin::new(500_000_000u64, "unym"),
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
simulator
|
||||
.delegate("delegator", Coin::new(7_000_000_000000, "unym"), n8)
|
||||
.delegate("delegator", Coin::new(7_000_000_000000u64, "unym"), n8)
|
||||
.unwrap();
|
||||
|
||||
let n9 = simulator
|
||||
.bond(
|
||||
Coin::new(1_000_000_000000, "unym"),
|
||||
Coin::new(1_000_000_000000u64, "unym"),
|
||||
NodeCostParams {
|
||||
profit_margin_percent: Percent::from_percentage_value(10).unwrap(),
|
||||
interval_operating_cost: Coin::new(40_000_000, "unym"),
|
||||
interval_operating_cost: Coin::new(40_000_000u64, "unym"),
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
simulator
|
||||
.delegate("delegator", Coin::new(7_000_000_000000, "unym"), n9)
|
||||
.delegate("delegator", Coin::new(7_000_000_000000u64, "unym"), n9)
|
||||
.unwrap();
|
||||
|
||||
let uptime_1 = Percent::from_percentage_value(100).unwrap();
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
use crate::ecash::error::EcashTicketError;
|
||||
use crate::Error;
|
||||
use cosmwasm_std::{from_binary, CosmosMsg, WasmMsg};
|
||||
use cosmwasm_std::{from_json, CosmosMsg, WasmMsg};
|
||||
use nym_credentials_interface::VerificationKeyAuth;
|
||||
use nym_ecash_contract_common::msg::ExecuteMsg;
|
||||
use nym_gateway_storage::GatewayStorage;
|
||||
@@ -72,7 +72,7 @@ impl SharedState {
|
||||
let CosmosMsg::Wasm(WasmMsg::Execute { msg, .. }) = msg else {
|
||||
return false;
|
||||
};
|
||||
let Ok(ExecuteMsg::RedeemTickets { gw, .. }) = from_binary(msg) else {
|
||||
let Ok(ExecuteMsg::RedeemTickets { gw, .. }) = from_json(msg) else {
|
||||
return false;
|
||||
};
|
||||
|
||||
|
||||
@@ -132,6 +132,10 @@ impl PublicKey {
|
||||
*self.0.as_bytes()
|
||||
}
|
||||
|
||||
pub fn as_bytes(&self) -> &[u8; PUBLIC_KEY_SIZE] {
|
||||
self.0.as_bytes()
|
||||
}
|
||||
|
||||
pub fn from_bytes(b: &[u8]) -> Result<Self, KeyRecoveryError> {
|
||||
if b.len() != PUBLIC_KEY_SIZE {
|
||||
return Err(KeyRecoveryError::InvalidSizePublicKey {
|
||||
@@ -228,7 +232,6 @@ impl<'a> From<&'a PrivateKey> for PublicKey {
|
||||
PublicKey((&pk.0).into())
|
||||
}
|
||||
}
|
||||
|
||||
impl FromStr for PrivateKey {
|
||||
type Err = KeyRecoveryError;
|
||||
|
||||
|
||||
@@ -6,7 +6,6 @@ use ed25519_dalek::{SecretKey, Signer, SigningKey};
|
||||
pub use ed25519_dalek::{Verifier, PUBLIC_KEY_LENGTH, SECRET_KEY_LENGTH, SIGNATURE_LENGTH};
|
||||
use nym_pemstore::traits::{PemStorableKey, PemStorableKeyPair};
|
||||
use std::fmt::{self, Debug, Display, Formatter};
|
||||
use std::hash::{Hash, Hasher};
|
||||
use std::str::FromStr;
|
||||
use thiserror::Error;
|
||||
use zeroize::{Zeroize, ZeroizeOnDrop};
|
||||
@@ -154,17 +153,9 @@ impl PemStorableKeyPair for KeyPair {
|
||||
}
|
||||
|
||||
/// ed25519 EdDSA Public Key
|
||||
#[derive(Copy, Clone, Eq, PartialEq)]
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Hash)]
|
||||
pub struct PublicKey(ed25519_dalek::VerifyingKey);
|
||||
|
||||
impl Hash for PublicKey {
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
// each public key has unique bytes representation which can be used
|
||||
// for the hash implementation
|
||||
self.to_bytes().hash(state)
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for PublicKey {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||
Display::fmt(&self.to_base58_string(), f)
|
||||
|
||||
@@ -16,3 +16,20 @@ pub mod bs58_ed25519_pubkey {
|
||||
PublicKey::from_base58_string(s).map_err(serde::de::Error::custom)
|
||||
}
|
||||
}
|
||||
|
||||
pub mod bs58_ed25519_signature {
|
||||
use crate::asymmetric::identity::Signature;
|
||||
use serde::{Deserialize, Deserializer, Serializer};
|
||||
|
||||
pub fn serialize<S: Serializer>(
|
||||
signature: &Signature,
|
||||
serializer: S,
|
||||
) -> Result<S::Ok, S::Error> {
|
||||
serializer.serialize_str(&signature.to_base58_string())
|
||||
}
|
||||
|
||||
pub fn deserialize<'de, D: Deserializer<'de>>(deserializer: D) -> Result<Signature, D::Error> {
|
||||
let s = String::deserialize(deserializer)?;
|
||||
Signature::from_base58_string(s).map_err(serde::de::Error::custom)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,11 +36,10 @@ use std::{
|
||||
|
||||
use hickory_resolver::{
|
||||
config::{LookupIpStrategy, NameServerConfigGroup, ResolverConfig, ResolverOpts},
|
||||
error::ResolveError,
|
||||
lookup_ip::LookupIpIntoIter,
|
||||
error::{ResolveError, ResolveErrorKind},
|
||||
lookup_ip::{LookupIp, LookupIpIntoIter},
|
||||
TokioAsyncResolver,
|
||||
};
|
||||
use hickory_resolver::{error::ResolveErrorKind, lookup_ip::LookupIp};
|
||||
use once_cell::sync::OnceCell;
|
||||
use reqwest::dns::{Addrs, Name, Resolve, Resolving};
|
||||
use tracing::warn;
|
||||
@@ -214,10 +213,7 @@ impl HickoryDnsResolver {
|
||||
/// Create a new resolver with a custom DoT based configuration. The options are overridden to look
|
||||
/// up for both IPv4 and IPv6 addresses to work with "happy eyeballs" algorithm.
|
||||
fn new_resolver() -> Result<TokioAsyncResolver, HickoryDnsError> {
|
||||
let mut name_servers = NameServerConfigGroup::google_tls();
|
||||
name_servers.merge(NameServerConfigGroup::google_https());
|
||||
// name_servers.merge(NameServerConfigGroup::google_h3());
|
||||
name_servers.merge(NameServerConfigGroup::quad9_tls());
|
||||
let mut name_servers = NameServerConfigGroup::quad9_tls();
|
||||
name_servers.merge(NameServerConfigGroup::quad9_https());
|
||||
name_servers.merge(NameServerConfigGroup::cloudflare_tls());
|
||||
name_servers.merge(NameServerConfigGroup::cloudflare_https());
|
||||
|
||||
@@ -23,14 +23,12 @@ const LENGTH_PREFIX_SIZE: usize = 2;
|
||||
// long for the buffer to fill up, since this kills latency.
|
||||
pub struct MultiIpPacketCodec {
|
||||
buffer: BytesMut,
|
||||
buffer_timeout: tokio::time::Interval,
|
||||
}
|
||||
|
||||
impl MultiIpPacketCodec {
|
||||
pub fn new(buffer_timeout: Duration) -> Self {
|
||||
pub fn new() -> Self {
|
||||
MultiIpPacketCodec {
|
||||
buffer: BytesMut::new(),
|
||||
buffer_timeout: tokio::time::interval(buffer_timeout),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,56 +38,81 @@ impl MultiIpPacketCodec {
|
||||
bundled_packets.extend_from_slice(&packet);
|
||||
bundled_packets.freeze()
|
||||
}
|
||||
}
|
||||
|
||||
// Append a packet to the buffer and return the buffer if it's full
|
||||
pub fn append_packet(&mut self, packet: Bytes) -> Option<Bytes> {
|
||||
let mut bundled_packets = BytesMut::new();
|
||||
self.encode(packet, &mut bundled_packets).unwrap();
|
||||
if bundled_packets.is_empty() {
|
||||
None
|
||||
} else {
|
||||
// log::info!("Sphinx packet utilization: {:.2}", self.buffer.len() as f64 / MAX_PACKET_SIZE as f64);
|
||||
Some(bundled_packets.freeze())
|
||||
impl Default for MultiIpPacketCodec {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
/// The packet that we encode and decode with the MultiIpPacketCodec into bundled multi-ip packets.
|
||||
/// The data here is the actual IP packet that we want to send, not the bundled packets.
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub enum IprPacket {
|
||||
Data(Bytes),
|
||||
Flush,
|
||||
}
|
||||
|
||||
impl IprPacket {
|
||||
pub fn as_bytes(&self) -> &[u8] {
|
||||
match self {
|
||||
IprPacket::Data(bytes) => bytes.as_ref(),
|
||||
IprPacket::Flush => &[],
|
||||
}
|
||||
}
|
||||
|
||||
// Flush the current buffer and return it.
|
||||
pub fn flush_current_buffer(&mut self) -> Bytes {
|
||||
let mut output_buffer = BytesMut::new();
|
||||
std::mem::swap(&mut output_buffer, &mut self.buffer);
|
||||
output_buffer.freeze()
|
||||
}
|
||||
|
||||
// Wait for the buffer_timeout to tick and then flush the buffer.
|
||||
// This is useful when we want to send the buffer even if it's not full.
|
||||
pub async fn buffer_timeout(&mut self) -> Option<Bytes> {
|
||||
// Wait for buffer_timeout to tick
|
||||
let _ = self.buffer_timeout.tick().await;
|
||||
|
||||
// Flush the buffer and return it
|
||||
let packets = self.flush_current_buffer();
|
||||
if packets.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(packets)
|
||||
pub fn into_bytes(self) -> Bytes {
|
||||
match self {
|
||||
IprPacket::Data(bytes) => bytes,
|
||||
IprPacket::Flush => Bytes::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Encoder<Bytes> for MultiIpPacketCodec {
|
||||
impl From<Bytes> for IprPacket {
|
||||
fn from(bytes: Bytes) -> Self {
|
||||
IprPacket::Data(bytes)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Vec<u8>> for IprPacket {
|
||||
fn from(bytes: Vec<u8>) -> Self {
|
||||
IprPacket::Data(Bytes::from(bytes))
|
||||
}
|
||||
}
|
||||
|
||||
impl Encoder<IprPacket> for MultiIpPacketCodec {
|
||||
type Error = Error;
|
||||
|
||||
fn encode(&mut self, packet: Bytes, dst: &mut BytesMut) -> Result<(), Self::Error> {
|
||||
if self.buffer.is_empty() {
|
||||
self.buffer_timeout.reset();
|
||||
}
|
||||
fn encode(&mut self, packet: IprPacket, dst: &mut BytesMut) -> Result<(), Self::Error> {
|
||||
let packet = match packet {
|
||||
IprPacket::Flush => {
|
||||
dst.extend_from_slice(&self.buffer);
|
||||
self.buffer = BytesMut::new();
|
||||
return Ok(());
|
||||
}
|
||||
IprPacket::Data(packet) => packet,
|
||||
};
|
||||
|
||||
let packet_size = packet.len();
|
||||
|
||||
// If the existing buffer is empty, and the packet is too large, send it directly
|
||||
if self.buffer.is_empty() && packet_size + LENGTH_PREFIX_SIZE > MAX_PACKET_SIZE {
|
||||
// Add the packet size
|
||||
dst.extend_from_slice(&(packet_size as u16).to_be_bytes());
|
||||
// Add the packet to the buffer
|
||||
dst.extend_from_slice(&packet);
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
// If the packet doesn't fit in the existing buffer, send what we have now in the buffer
|
||||
// and then add it to the next buffer
|
||||
if self.buffer.len() + packet_size + LENGTH_PREFIX_SIZE > MAX_PACKET_SIZE {
|
||||
// If the packet doesn't fit in the buffer, send the buffer and then add it to the buffer
|
||||
// Send the existing buffer
|
||||
dst.extend_from_slice(&self.buffer);
|
||||
// Start a new buffer
|
||||
self.buffer = BytesMut::new();
|
||||
self.buffer_timeout.reset();
|
||||
}
|
||||
|
||||
// Add the packet size
|
||||
@@ -103,7 +126,7 @@ impl Encoder<Bytes> for MultiIpPacketCodec {
|
||||
}
|
||||
|
||||
impl Decoder for MultiIpPacketCodec {
|
||||
type Item = Bytes;
|
||||
type Item = IprPacket;
|
||||
type Error = Error;
|
||||
|
||||
fn decode(&mut self, src: &mut BytesMut) -> Result<Option<Self::Item>, Self::Error> {
|
||||
@@ -125,6 +148,86 @@ impl Decoder for MultiIpPacketCodec {
|
||||
// Read the packet
|
||||
let packet = src.split_to(packet_size);
|
||||
|
||||
Ok(Some(packet.freeze()))
|
||||
Ok(Some(IprPacket::Data(packet.freeze())))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_multi_ip_packet_codec_max_packet_size() {
|
||||
let mut codec = MultiIpPacketCodec::new();
|
||||
let mut buffer = BytesMut::new();
|
||||
|
||||
// A packet size that is large enough that two packets won't fit in the buffer
|
||||
const PACKET_SIZE: usize = MAX_PACKET_SIZE - 100;
|
||||
|
||||
let packet1 = IprPacket::from(Bytes::from_static(&[0u8; PACKET_SIZE]));
|
||||
let packet2 = IprPacket::from(Bytes::from_static(&[0u8; PACKET_SIZE]));
|
||||
|
||||
codec.encode(packet1.clone(), &mut buffer).unwrap();
|
||||
assert_eq!(buffer.len(), 0);
|
||||
|
||||
codec.encode(packet2.clone(), &mut buffer).unwrap();
|
||||
assert_eq!(buffer.len(), LENGTH_PREFIX_SIZE + PACKET_SIZE);
|
||||
|
||||
// First is the length prefix
|
||||
assert_eq!(buffer[..2], (PACKET_SIZE as u16).to_be_bytes());
|
||||
// Next is the packet
|
||||
assert_eq!(&buffer[2..], packet1.as_bytes());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn encode_and_then_decode() {
|
||||
let mut codec = MultiIpPacketCodec::new();
|
||||
let mut buffer = BytesMut::new();
|
||||
|
||||
let packet = IprPacket::from(Bytes::from_static(&[0u8; 1000]));
|
||||
codec.encode(packet.clone(), &mut buffer).unwrap();
|
||||
codec.encode(packet.clone(), &mut buffer).unwrap();
|
||||
|
||||
let mut decoded_packets = Vec::new();
|
||||
while let Some(decoded_packet) = codec.decode(&mut buffer).unwrap() {
|
||||
decoded_packets.push(decoded_packet);
|
||||
}
|
||||
|
||||
assert_eq!(decoded_packets.len(), 1);
|
||||
assert_eq!(decoded_packets[0].as_bytes(), packet.as_bytes());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn encode_a_packat_that_is_too_large() {
|
||||
let mut codec = MultiIpPacketCodec::new();
|
||||
let mut buffer = BytesMut::new();
|
||||
|
||||
let packet = IprPacket::from(Bytes::from_static(
|
||||
&[0u8; MAX_PACKET_SIZE + MAX_PACKET_SIZE],
|
||||
));
|
||||
codec.encode(packet, &mut buffer).unwrap();
|
||||
assert_eq!(
|
||||
buffer.len(),
|
||||
MAX_PACKET_SIZE + MAX_PACKET_SIZE + LENGTH_PREFIX_SIZE
|
||||
);
|
||||
codec.encode(IprPacket::Flush, &mut buffer).unwrap();
|
||||
assert_eq!(
|
||||
buffer.len(),
|
||||
MAX_PACKET_SIZE + MAX_PACKET_SIZE + LENGTH_PREFIX_SIZE
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn check_that_max_size_does_not_flush() {
|
||||
let mut codec = MultiIpPacketCodec::new();
|
||||
let mut buffer = BytesMut::new();
|
||||
|
||||
let packet = IprPacket::from(Bytes::from_static(&[0u8; MAX_PACKET_SIZE - 2]));
|
||||
codec.encode(packet.clone(), &mut buffer).unwrap();
|
||||
assert_eq!(buffer.len(), 0);
|
||||
|
||||
let packet = IprPacket::from(Bytes::from_static(&[0u8; MAX_PACKET_SIZE - 2]));
|
||||
codec.encode(packet.clone(), &mut buffer).unwrap();
|
||||
assert_eq!(buffer.len(), MAX_PACKET_SIZE);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,9 @@ pub const TICKETBOOK_VALIDITY_DAYS: u32 = 7;
|
||||
/// Specifies the number of tickets in each issued ticketbook.
|
||||
pub const TICKETBOOK_SIZE: u64 = 50;
|
||||
|
||||
/// Specifies the minimum request size each signer must support
|
||||
pub const MINIMUM_TICKETBOOK_DATA_REQUEST_SIZE: usize = 50;
|
||||
|
||||
/// This type is defined mostly for the purposes of having constants (like sizes) associated with given variants
|
||||
/// It's not meant to be serialised or have any fancy traits defined on it (in this crate)
|
||||
#[derive(Copy, Clone, Debug, PartialEq)]
|
||||
|
||||
@@ -269,9 +269,8 @@ pub fn check_vk_pairing(
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use rand::RngCore;
|
||||
|
||||
use super::*;
|
||||
use rand::RngCore;
|
||||
|
||||
#[test]
|
||||
fn polynomial_evaluation() {
|
||||
|
||||
@@ -4,6 +4,7 @@ use crate::fragment::Fragment;
|
||||
use crate::{monitoring, ChunkingError};
|
||||
use log::*;
|
||||
use std::collections::HashMap;
|
||||
use std::time::{Duration, Instant};
|
||||
|
||||
// TODO: perhaps a more sophisticated approach with writing to disk periodically in case
|
||||
// we're receiving fast & furious in uncompressed 4K - we don't want to keep that in memory;
|
||||
@@ -31,6 +32,9 @@ struct ReconstructionBuffer {
|
||||
/// appropriately resized and all missing fragments are set to a `None`, thus keeping
|
||||
/// everything in order the whole time, allowing for O(1) insertions and O(n) reconstruction.
|
||||
fragments: Vec<Option<Fragment>>,
|
||||
|
||||
/// The timestamp of the last received fragment. Used for cleaning up stale buffers.
|
||||
last_fragment_timestamp: Instant,
|
||||
}
|
||||
|
||||
/// Type alias representing fully reconstructed message - its original data and list of all
|
||||
@@ -56,6 +60,7 @@ impl ReconstructionBuffer {
|
||||
previous_fragments_set_id: None,
|
||||
next_fragments_set_id: None,
|
||||
fragments: fragments_buffer,
|
||||
last_fragment_timestamp: Instant::now(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -99,6 +104,8 @@ impl ReconstructionBuffer {
|
||||
/// `previous_fragments_set_id` and `next_fragments_set_id` are set for the ease
|
||||
/// of access.
|
||||
fn insert_fragment(&mut self, fragment: Fragment) {
|
||||
self.last_fragment_timestamp = Instant::now();
|
||||
|
||||
// all fragments in the buffer should always have the same id as before inserting an element,
|
||||
// the correct buffer instance is looked up based on the fragment to be inserted.
|
||||
debug_assert!({
|
||||
@@ -158,6 +165,10 @@ pub struct MessageReconstructor {
|
||||
}
|
||||
|
||||
impl MessageReconstructor {
|
||||
// We want to be very conservative here. We remove these to avoid memory leaks, but it's okay
|
||||
// to wait for a long time before we do so.
|
||||
const INCOMPLETE_MESSAGE_TIMEOUT: Duration = Duration::from_secs(30 * 60);
|
||||
|
||||
/// Creates an empty `MessageReconstructor`.
|
||||
pub fn new() -> Self {
|
||||
Default::default()
|
||||
@@ -296,6 +307,25 @@ impl MessageReconstructor {
|
||||
pub fn recover_fragment(&self, fragment_data: Vec<u8>) -> Result<Fragment, ChunkingError> {
|
||||
Fragment::try_from_bytes(&fragment_data)
|
||||
}
|
||||
|
||||
pub fn cleanup_stale_buffers(&mut self) {
|
||||
trace!("Cleaning up stale buffers");
|
||||
let now = Instant::now();
|
||||
self.reconstructed_sets.retain(|_, set_buf| {
|
||||
let keep = now.duration_since(set_buf.last_fragment_timestamp)
|
||||
< Self::INCOMPLETE_MESSAGE_TIMEOUT;
|
||||
if !keep {
|
||||
debug!(
|
||||
"Removing stale buffer for set id {:?}",
|
||||
set_buf
|
||||
.fragments
|
||||
.first()
|
||||
.and_then(|f| f.as_ref().map(|f| f.id()))
|
||||
);
|
||||
}
|
||||
keep
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
@@ -508,6 +538,8 @@ mod reconstruction_buffer {
|
||||
|
||||
#[cfg(test)]
|
||||
mod message_reconstructor {
|
||||
use std::time::Instant;
|
||||
|
||||
use super::*;
|
||||
use crate::fragment::unlinked_fragment_payload_max_len;
|
||||
use crate::set::{max_one_way_linked_set_payload_length, two_way_linked_set_payload_length};
|
||||
@@ -869,6 +901,7 @@ mod message_reconstructor {
|
||||
previous_fragments_set_id: None,
|
||||
next_fragments_set_id: None,
|
||||
fragments: vec![],
|
||||
last_fragment_timestamp: Instant::now(),
|
||||
},
|
||||
);
|
||||
|
||||
@@ -879,6 +912,7 @@ mod message_reconstructor {
|
||||
previous_fragments_set_id: None,
|
||||
next_fragments_set_id: None,
|
||||
fragments: vec![],
|
||||
last_fragment_timestamp: Instant::now(),
|
||||
},
|
||||
);
|
||||
|
||||
@@ -1006,6 +1040,7 @@ mod message_reconstructor {
|
||||
previous_fragments_set_id: None,
|
||||
next_fragments_set_id: Some(1234),
|
||||
fragments: vec![],
|
||||
last_fragment_timestamp: Instant::now(),
|
||||
},
|
||||
);
|
||||
|
||||
@@ -1016,6 +1051,7 @@ mod message_reconstructor {
|
||||
previous_fragments_set_id: Some(12345),
|
||||
next_fragments_set_id: Some(123),
|
||||
fragments: vec![],
|
||||
last_fragment_timestamp: Instant::now(),
|
||||
},
|
||||
);
|
||||
|
||||
@@ -1026,6 +1062,7 @@ mod message_reconstructor {
|
||||
previous_fragments_set_id: Some(1234),
|
||||
next_fragments_set_id: Some(12),
|
||||
fragments: vec![],
|
||||
last_fragment_timestamp: Instant::now(),
|
||||
},
|
||||
);
|
||||
|
||||
@@ -1036,6 +1073,7 @@ mod message_reconstructor {
|
||||
previous_fragments_set_id: Some(123),
|
||||
next_fragments_set_id: None,
|
||||
fragments: vec![],
|
||||
last_fragment_timestamp: Instant::now(),
|
||||
},
|
||||
);
|
||||
|
||||
@@ -1083,6 +1121,7 @@ mod message_reconstructor {
|
||||
previous_fragments_set_id: None,
|
||||
next_fragments_set_id: Some(1234),
|
||||
fragments: vec![],
|
||||
last_fragment_timestamp: Instant::now(),
|
||||
},
|
||||
);
|
||||
reconstructor.reconstructed_sets.insert(
|
||||
@@ -1092,6 +1131,7 @@ mod message_reconstructor {
|
||||
previous_fragments_set_id: Some(12345),
|
||||
next_fragments_set_id: None,
|
||||
fragments: vec![],
|
||||
last_fragment_timestamp: Instant::now(),
|
||||
},
|
||||
);
|
||||
assert_eq!(reconstructor.previous_linked_set_id(12345), None);
|
||||
@@ -1139,6 +1179,7 @@ mod message_reconstructor {
|
||||
previous_fragments_set_id: None,
|
||||
next_fragments_set_id: Some(1234),
|
||||
fragments: vec![],
|
||||
last_fragment_timestamp: Instant::now(),
|
||||
},
|
||||
);
|
||||
reconstructor.reconstructed_sets.insert(
|
||||
@@ -1148,6 +1189,7 @@ mod message_reconstructor {
|
||||
previous_fragments_set_id: Some(12345),
|
||||
next_fragments_set_id: None,
|
||||
fragments: vec![],
|
||||
last_fragment_timestamp: Instant::now(),
|
||||
},
|
||||
);
|
||||
assert_eq!(reconstructor.next_linked_set_id(12345), Some(1234));
|
||||
|
||||
@@ -8,7 +8,7 @@ use thiserror::Error;
|
||||
use nym_outfox::packet::{OutfoxPacket, OutfoxProcessedPacket};
|
||||
|
||||
#[cfg(feature = "sphinx")]
|
||||
use sphinx_packet::{SphinxPacket, SphinxPacketBuilder};
|
||||
pub use sphinx_packet::{SphinxPacket, SphinxPacketBuilder};
|
||||
|
||||
#[cfg(feature = "outfox")]
|
||||
pub use nym_outfox::{
|
||||
@@ -166,4 +166,20 @@ impl NymPacket {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "sphinx")]
|
||||
pub fn sphinx_packet_ref(&self) -> Option<&SphinxPacket> {
|
||||
match self {
|
||||
NymPacket::Sphinx(packet) => Some(packet),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "sphinx")]
|
||||
pub fn as_sphinx_packet(self) -> Option<SphinxPacket> {
|
||||
match self {
|
||||
NymPacket::Sphinx(packet) => Some(packet),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,12 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use futures::channel::mpsc;
|
||||
use std::collections::HashMap;
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
time::{Duration, Instant},
|
||||
};
|
||||
|
||||
const LANE_CONSIDERED_CLEAR: usize = 10;
|
||||
|
||||
pub type ConnectionId = u64;
|
||||
|
||||
@@ -67,6 +72,32 @@ impl LaneQueueLengths {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn total(&self) -> usize {
|
||||
match self.0.lock() {
|
||||
Ok(inner) => inner.values().sum(),
|
||||
Err(err) => {
|
||||
log::warn!("Failed to get total queue length: {err}");
|
||||
0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn wait_until_clear(&self, lane: &TransmissionLane, timeout: Option<Duration>) {
|
||||
let total_time_waited = Instant::now();
|
||||
loop {
|
||||
let lane_length = self.get(lane).unwrap_or_default();
|
||||
if lane_length < LANE_CONSIDERED_CLEAR {
|
||||
break;
|
||||
}
|
||||
if timeout.is_some_and(|timeout| total_time_waited.elapsed() > timeout) {
|
||||
log::warn!("Timeout reached while waiting for queue to clear");
|
||||
break;
|
||||
}
|
||||
log::trace!("Waiting for queue to clear ({} items left)", lane_length);
|
||||
tokio::time::sleep(Duration::from_millis(100)).await;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for LaneQueueLengths {
|
||||
|
||||
@@ -363,7 +363,7 @@ impl TaskClient {
|
||||
"unnamed-TaskClient".to_string()
|
||||
};
|
||||
|
||||
log!(target: target, level, "{}", format!("[{target}] {msg}"))
|
||||
log!(target: target, level, "{}", format_args!("[{target}] {msg}"))
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
|
||||
@@ -176,6 +176,7 @@ pub struct IssuedTicketbooksFullMerkleProof {
|
||||
included_leaves: Vec<MerkleLeaf>,
|
||||
total_leaves: usize,
|
||||
#[schemars(with = "String")]
|
||||
#[schema(value_type = String)]
|
||||
#[serde(with = "nym_serde_helpers::hex")]
|
||||
root: Vec<u8>,
|
||||
}
|
||||
|
||||
@@ -6,13 +6,12 @@ use base64::engine::general_purpose;
|
||||
use base64::Engine;
|
||||
use serde::Serialize;
|
||||
use std::fmt;
|
||||
use std::hash::{Hash, Hasher};
|
||||
use std::ops::Deref;
|
||||
use std::str::FromStr;
|
||||
|
||||
use x25519_dalek::PublicKey;
|
||||
|
||||
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
|
||||
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
|
||||
pub struct PeerPublicKey(PublicKey);
|
||||
|
||||
impl PeerPublicKey {
|
||||
@@ -36,12 +35,6 @@ impl fmt::Display for PeerPublicKey {
|
||||
}
|
||||
}
|
||||
|
||||
impl Hash for PeerPublicKey {
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
self.0.as_bytes().hash(state)
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for PeerPublicKey {
|
||||
type Target = PublicKey;
|
||||
|
||||
|
||||
@@ -102,7 +102,7 @@ impl PeerHandle {
|
||||
if SystemTime::now().duration_since(self.startup_timestamp)? >= AUTO_REMOVE_AFTER {
|
||||
log::debug!(
|
||||
"Peer {} has been present for 30 days, removing it",
|
||||
self.public_key.to_string()
|
||||
self.public_key
|
||||
);
|
||||
let success = self.remove_peer().await?;
|
||||
return Ok(!success);
|
||||
@@ -111,7 +111,7 @@ impl PeerHandle {
|
||||
if spent_bandwidth >= BANDWIDTH_CAP_PER_DAY {
|
||||
log::debug!(
|
||||
"Peer {} doesn't have bandwidth anymore, removing it",
|
||||
self.public_key.to_string()
|
||||
self.public_key
|
||||
);
|
||||
let success = self.remove_peer().await?;
|
||||
return Ok(!success);
|
||||
|
||||
Generated
+567
-495
File diff suppressed because it is too large
Load Diff
+17
-19
@@ -1,9 +1,7 @@
|
||||
[workspace]
|
||||
resolver = "2"
|
||||
members = [
|
||||
# "coconut-bandwidth",
|
||||
"coconut-dkg",
|
||||
"coconut-test",
|
||||
"ecash",
|
||||
"mixnet",
|
||||
"mixnet-vesting-integration-tests",
|
||||
@@ -33,24 +31,24 @@ overflow-checks = true
|
||||
|
||||
[workspace.dependencies]
|
||||
anyhow = "1.0.86"
|
||||
bs58 = "0.4.0"
|
||||
cosmwasm-crypto = "=1.4.3"
|
||||
cosmwasm-derive = "=1.4.3"
|
||||
cosmwasm-schema = "=1.4.3"
|
||||
cosmwasm-std = "=1.4.3"
|
||||
cosmwasm-storage = "=1.4.3"
|
||||
cw-controllers = "=1.1.0"
|
||||
cw-multi-test = "=0.16.5"
|
||||
cw-storage-plus = "=1.2.0"
|
||||
cw-utils = "=1.0.1"
|
||||
cw2 = "=1.1.2"
|
||||
cw3 = "=1.1.2"
|
||||
cw3-fixed-multisig = "=1.1.2"
|
||||
cw4 = "=1.1.2"
|
||||
cw20 = "=1.1.2"
|
||||
bs58 = "0.5.1"
|
||||
cosmwasm-crypto = "=2.2.2"
|
||||
cosmwasm-derive = "=2.2.2"
|
||||
cosmwasm-schema = "=2.2.2"
|
||||
cosmwasm-std = "=2.2.2"
|
||||
cw-controllers = "=2.0.0"
|
||||
cw-multi-test = "=2.3.2"
|
||||
cw-storage-plus = "=2.0.0"
|
||||
cw-utils = "=2.0.0"
|
||||
cw2 = "=2.0.0"
|
||||
cw3 = "=2.0.0"
|
||||
cw3-fixed-multisig = "=2.0.0"
|
||||
cw4 = "=2.0.0"
|
||||
cw20 = "=2.0.0"
|
||||
cw20-base = "2.0.0"
|
||||
semver = "1.0.21"
|
||||
serde = "1.0.196"
|
||||
sylvia = "0.8.0"
|
||||
sylvia = "1.3.3"
|
||||
schemars = "0.8.16"
|
||||
|
||||
thiserror = "1.0.48"
|
||||
thiserror = "2.0.11"
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
schema: coconut-dkg-schema mixnet-schema vesting-schema multisig-schema group-schema ecash-schema
|
||||
|
||||
#coconut-bandwidth-schema:
|
||||
# $(MAKE) -C coconut-bandwidth generate-schema
|
||||
|
||||
coconut-dkg-schema:
|
||||
$(MAKE) -C coconut-dkg generate-schema
|
||||
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
[alias]
|
||||
wasm = "build --release --lib --target wasm32-unknown-unknown"
|
||||
unit-test = "test --lib"
|
||||
schema = "run --bin schema --features=schema-gen"
|
||||
@@ -1,29 +0,0 @@
|
||||
[package]
|
||||
name = "nym-coconut-bandwidth"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[[bin]]
|
||||
name = "schema"
|
||||
required-features = ["schema-gen"]
|
||||
|
||||
[lib]
|
||||
crate-type = ["cdylib", "rlib"]
|
||||
|
||||
[dependencies]
|
||||
nym-coconut-bandwidth-contract-common = { path = "../../common/cosmwasm-smart-contracts/coconut-bandwidth-contract" }
|
||||
nym-multisig-contract-common = { path = "../../common/cosmwasm-smart-contracts/multisig-contract" }
|
||||
|
||||
cosmwasm-std = { workspace = true }
|
||||
cosmwasm-schema = { workspace = true, optional = true }
|
||||
cosmwasm-storage = { workspace = true }
|
||||
cw-storage-plus = { workspace = true }
|
||||
cw-controllers = { workspace = true }
|
||||
|
||||
serde = { version = "1.0.103", default-features = false, features = ["derive"] }
|
||||
thiserror = { workspace = true }
|
||||
|
||||
[features]
|
||||
schema-gen = ["nym-coconut-bandwidth-contract-common/schema", "cosmwasm-schema"]
|
||||
@@ -1,2 +0,0 @@
|
||||
generate-schema:
|
||||
cargo schema
|
||||
@@ -1,382 +0,0 @@
|
||||
{
|
||||
"contract_name": "nym-coconut-bandwidth",
|
||||
"contract_version": "0.1.0",
|
||||
"idl_version": "1.0.0",
|
||||
"instantiate": {
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"title": "InstantiateMsg",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"mix_denom",
|
||||
"multisig_addr",
|
||||
"pool_addr"
|
||||
],
|
||||
"properties": {
|
||||
"mix_denom": {
|
||||
"type": "string"
|
||||
},
|
||||
"multisig_addr": {
|
||||
"type": "string"
|
||||
},
|
||||
"pool_addr": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"execute": {
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"title": "ExecuteMsg",
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "object",
|
||||
"required": [
|
||||
"deposit_funds"
|
||||
],
|
||||
"properties": {
|
||||
"deposit_funds": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"data"
|
||||
],
|
||||
"properties": {
|
||||
"data": {
|
||||
"$ref": "#/definitions/DepositData"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"required": [
|
||||
"spend_credential"
|
||||
],
|
||||
"properties": {
|
||||
"spend_credential": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"data"
|
||||
],
|
||||
"properties": {
|
||||
"data": {
|
||||
"$ref": "#/definitions/SpendCredentialData"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"required": [
|
||||
"release_funds"
|
||||
],
|
||||
"properties": {
|
||||
"release_funds": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"funds"
|
||||
],
|
||||
"properties": {
|
||||
"funds": {
|
||||
"$ref": "#/definitions/Coin"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
],
|
||||
"definitions": {
|
||||
"Coin": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"amount",
|
||||
"denom"
|
||||
],
|
||||
"properties": {
|
||||
"amount": {
|
||||
"$ref": "#/definitions/Uint128"
|
||||
},
|
||||
"denom": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"DepositData": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"deposit_info",
|
||||
"encryption_key",
|
||||
"identity_key"
|
||||
],
|
||||
"properties": {
|
||||
"deposit_info": {
|
||||
"type": "string"
|
||||
},
|
||||
"encryption_key": {
|
||||
"type": "string"
|
||||
},
|
||||
"identity_key": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"SpendCredentialData": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"blinded_serial_number",
|
||||
"funds",
|
||||
"gateway_cosmos_address"
|
||||
],
|
||||
"properties": {
|
||||
"blinded_serial_number": {
|
||||
"type": "string"
|
||||
},
|
||||
"funds": {
|
||||
"$ref": "#/definitions/Coin"
|
||||
},
|
||||
"gateway_cosmos_address": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"Uint128": {
|
||||
"description": "A thin wrapper around u128 that is using strings for JSON encoding/decoding, such that the full u128 range can be used for clients that convert JSON numbers to floats, like JavaScript and jq.\n\n# Examples\n\nUse `from` to create instances of this and `u128` to get the value out:\n\n``` # use cosmwasm_std::Uint128; let a = Uint128::from(123u128); assert_eq!(a.u128(), 123);\n\nlet b = Uint128::from(42u64); assert_eq!(b.u128(), 42);\n\nlet c = Uint128::from(70u32); assert_eq!(c.u128(), 70); ```",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"query": {
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"title": "QueryMsg",
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "object",
|
||||
"required": [
|
||||
"get_spent_credential"
|
||||
],
|
||||
"properties": {
|
||||
"get_spent_credential": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"blinded_serial_number"
|
||||
],
|
||||
"properties": {
|
||||
"blinded_serial_number": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"required": [
|
||||
"get_all_spent_credentials"
|
||||
],
|
||||
"properties": {
|
||||
"get_all_spent_credentials": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"limit": {
|
||||
"type": [
|
||||
"integer",
|
||||
"null"
|
||||
],
|
||||
"format": "uint32",
|
||||
"minimum": 0.0
|
||||
},
|
||||
"start_after": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
]
|
||||
},
|
||||
"migrate": {
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"title": "MigrateMsg",
|
||||
"type": "object",
|
||||
"additionalProperties": false
|
||||
},
|
||||
"sudo": null,
|
||||
"responses": {
|
||||
"get_all_spent_credentials": {
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"title": "PagedSpendCredentialResponse",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"per_page",
|
||||
"spend_credentials"
|
||||
],
|
||||
"properties": {
|
||||
"per_page": {
|
||||
"type": "integer",
|
||||
"format": "uint",
|
||||
"minimum": 0.0
|
||||
},
|
||||
"spend_credentials": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/SpendCredential"
|
||||
}
|
||||
},
|
||||
"start_next_after": {
|
||||
"description": "Field indicating paging information for the following queries if the caller wishes to get further entries.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
"definitions": {
|
||||
"Addr": {
|
||||
"description": "A human readable address.\n\nIn Cosmos, this is typically bech32 encoded. But for multi-chain smart contracts no assumptions should be made other than being UTF-8 encoded and of reasonable length.\n\nThis type represents a validated address. It can be created in the following ways 1. Use `Addr::unchecked(input)` 2. Use `let checked: Addr = deps.api.addr_validate(input)?` 3. Use `let checked: Addr = deps.api.addr_humanize(canonical_addr)?` 4. Deserialize from JSON. This must only be done from JSON that was validated before such as a contract's state. `Addr` must not be used in messages sent by the user because this would result in unvalidated instances.\n\nThis type is immutable. If you really need to mutate it (Really? Are you sure?), create a mutable copy using `let mut mutable = Addr::to_string()` and operate on that `String` instance.",
|
||||
"type": "string"
|
||||
},
|
||||
"Coin": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"amount",
|
||||
"denom"
|
||||
],
|
||||
"properties": {
|
||||
"amount": {
|
||||
"$ref": "#/definitions/Uint128"
|
||||
},
|
||||
"denom": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"SpendCredential": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"blinded_serial_number",
|
||||
"funds",
|
||||
"gateway_cosmos_address",
|
||||
"status"
|
||||
],
|
||||
"properties": {
|
||||
"blinded_serial_number": {
|
||||
"type": "string"
|
||||
},
|
||||
"funds": {
|
||||
"$ref": "#/definitions/Coin"
|
||||
},
|
||||
"gateway_cosmos_address": {
|
||||
"$ref": "#/definitions/Addr"
|
||||
},
|
||||
"status": {
|
||||
"$ref": "#/definitions/SpendCredentialStatus"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"SpendCredentialStatus": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"in_progress",
|
||||
"spent"
|
||||
]
|
||||
},
|
||||
"Uint128": {
|
||||
"description": "A thin wrapper around u128 that is using strings for JSON encoding/decoding, such that the full u128 range can be used for clients that convert JSON numbers to floats, like JavaScript and jq.\n\n# Examples\n\nUse `from` to create instances of this and `u128` to get the value out:\n\n``` # use cosmwasm_std::Uint128; let a = Uint128::from(123u128); assert_eq!(a.u128(), 123);\n\nlet b = Uint128::from(42u64); assert_eq!(b.u128(), 42);\n\nlet c = Uint128::from(70u32); assert_eq!(c.u128(), 70); ```",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"get_spent_credential": {
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"title": "SpendCredentialResponse",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"spend_credential": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/SpendCredential"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
"definitions": {
|
||||
"Addr": {
|
||||
"description": "A human readable address.\n\nIn Cosmos, this is typically bech32 encoded. But for multi-chain smart contracts no assumptions should be made other than being UTF-8 encoded and of reasonable length.\n\nThis type represents a validated address. It can be created in the following ways 1. Use `Addr::unchecked(input)` 2. Use `let checked: Addr = deps.api.addr_validate(input)?` 3. Use `let checked: Addr = deps.api.addr_humanize(canonical_addr)?` 4. Deserialize from JSON. This must only be done from JSON that was validated before such as a contract's state. `Addr` must not be used in messages sent by the user because this would result in unvalidated instances.\n\nThis type is immutable. If you really need to mutate it (Really? Are you sure?), create a mutable copy using `let mut mutable = Addr::to_string()` and operate on that `String` instance.",
|
||||
"type": "string"
|
||||
},
|
||||
"Coin": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"amount",
|
||||
"denom"
|
||||
],
|
||||
"properties": {
|
||||
"amount": {
|
||||
"$ref": "#/definitions/Uint128"
|
||||
},
|
||||
"denom": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"SpendCredential": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"blinded_serial_number",
|
||||
"funds",
|
||||
"gateway_cosmos_address",
|
||||
"status"
|
||||
],
|
||||
"properties": {
|
||||
"blinded_serial_number": {
|
||||
"type": "string"
|
||||
},
|
||||
"funds": {
|
||||
"$ref": "#/definitions/Coin"
|
||||
},
|
||||
"gateway_cosmos_address": {
|
||||
"$ref": "#/definitions/Addr"
|
||||
},
|
||||
"status": {
|
||||
"$ref": "#/definitions/SpendCredentialStatus"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"SpendCredentialStatus": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"in_progress",
|
||||
"spent"
|
||||
]
|
||||
},
|
||||
"Uint128": {
|
||||
"description": "A thin wrapper around u128 that is using strings for JSON encoding/decoding, such that the full u128 range can be used for clients that convert JSON numbers to floats, like JavaScript and jq.\n\n# Examples\n\nUse `from` to create instances of this and `u128` to get the value out:\n\n``` # use cosmwasm_std::Uint128; let a = Uint128::from(123u128); assert_eq!(a.u128(), 123);\n\nlet b = Uint128::from(42u64); assert_eq!(b.u128(), 42);\n\nlet c = Uint128::from(70u32); assert_eq!(c.u128(), 70); ```",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,130 +0,0 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"title": "ExecuteMsg",
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "object",
|
||||
"required": [
|
||||
"deposit_funds"
|
||||
],
|
||||
"properties": {
|
||||
"deposit_funds": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"data"
|
||||
],
|
||||
"properties": {
|
||||
"data": {
|
||||
"$ref": "#/definitions/DepositData"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"required": [
|
||||
"spend_credential"
|
||||
],
|
||||
"properties": {
|
||||
"spend_credential": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"data"
|
||||
],
|
||||
"properties": {
|
||||
"data": {
|
||||
"$ref": "#/definitions/SpendCredentialData"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"required": [
|
||||
"release_funds"
|
||||
],
|
||||
"properties": {
|
||||
"release_funds": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"funds"
|
||||
],
|
||||
"properties": {
|
||||
"funds": {
|
||||
"$ref": "#/definitions/Coin"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
],
|
||||
"definitions": {
|
||||
"Coin": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"amount",
|
||||
"denom"
|
||||
],
|
||||
"properties": {
|
||||
"amount": {
|
||||
"$ref": "#/definitions/Uint128"
|
||||
},
|
||||
"denom": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"DepositData": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"deposit_info",
|
||||
"encryption_key",
|
||||
"identity_key"
|
||||
],
|
||||
"properties": {
|
||||
"deposit_info": {
|
||||
"type": "string"
|
||||
},
|
||||
"encryption_key": {
|
||||
"type": "string"
|
||||
},
|
||||
"identity_key": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"SpendCredentialData": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"blinded_serial_number",
|
||||
"funds",
|
||||
"gateway_cosmos_address"
|
||||
],
|
||||
"properties": {
|
||||
"blinded_serial_number": {
|
||||
"type": "string"
|
||||
},
|
||||
"funds": {
|
||||
"$ref": "#/definitions/Coin"
|
||||
},
|
||||
"gateway_cosmos_address": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"Uint128": {
|
||||
"description": "A thin wrapper around u128 that is using strings for JSON encoding/decoding, such that the full u128 range can be used for clients that convert JSON numbers to floats, like JavaScript and jq.\n\n# Examples\n\nUse `from` to create instances of this and `u128` to get the value out:\n\n``` # use cosmwasm_std::Uint128; let a = Uint128::from(123u128); assert_eq!(a.u128(), 123);\n\nlet b = Uint128::from(42u64); assert_eq!(b.u128(), 42);\n\nlet c = Uint128::from(70u32); assert_eq!(c.u128(), 70); ```",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"title": "InstantiateMsg",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"mix_denom",
|
||||
"multisig_addr",
|
||||
"pool_addr"
|
||||
],
|
||||
"properties": {
|
||||
"mix_denom": {
|
||||
"type": "string"
|
||||
},
|
||||
"multisig_addr": {
|
||||
"type": "string"
|
||||
},
|
||||
"pool_addr": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user