Skip to content

Commit 9ed6c7e

Browse files
committed
fix: broken smart contract decryption; feat: updated DiscreteERC20 with encrypted callback
1 parent 9f15571 commit 9ed6c7e

12 files changed

+1086
-383
lines changed

.prettierignore

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
contracts/BigNum.sol

.prettierrc.json

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
{
2+
"printWidth": 120,
3+
"plugins": ["@trivago/prettier-plugin-sort-imports", "prettier-plugin-solidity"],
4+
"overrides": [
5+
{
6+
"files": ["*.ts", ".js", ".cjs"],
7+
"options": {
8+
"singleQuote": true,
9+
"importOrder": ["<THIRD_PARTY_MODULES>", "^[./]"],
10+
"importOrderParserPlugins": ["typescript"],
11+
"importOrderSeparation": true,
12+
"importOrderSortSpecifiers": true
13+
}
14+
},
15+
{
16+
"files": "*.sol",
17+
"options": {
18+
"singleQuote": false
19+
}
20+
}
21+
]
22+
}

README.md

+63-63
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ To use this smart contract, you need to deploy it on the Ethereum blockchain. Yo
2323

2424
# Use Cases
2525

26-
The Paillier cryptosystem, which is homomorphic with respect to addition and multiplication, can be applied in various blockchain-based applications that require privacy-preserving computation.
26+
The Paillier cryptosystem, which is homomorphic with respect to addition and multiplication, can be applied in various blockchain-based applications that require privacy-preserving computation.
2727

2828
Included is a comprehensive [DiscreteERC20](contracts/examples/DiscreteERC20.sol) contract, demonstrating the library's homomorphic properties with an Ethereum Token, preserving transaction privacy onchain.
2929

@@ -40,26 +40,26 @@ pragma solidity ^0.8.24;
4040
import "./Paillier.sol";
4141
4242
contract PrivateVoting {
43-
Paillier public paillier;
44-
address public owner;
45-
BigNumber[] public encryptedVotes;
46-
47-
constructor(address _paillier) {
48-
paillier = Paillier(_paillier);
49-
owner = msg.sender;
50-
}
51-
52-
function submitVote(bytes calldata vote, bytes calldata publicKey) public {
53-
encryptedVotes.push(BigNumber(vote, false, BigNum.bitLength(vote)));
54-
}
55-
56-
function tallyVotes(bytes calldata publicKey) public view returns (BigNumber memory) {
57-
BigNumber memory total = encryptedVotes[0];
58-
for (uint256 i = 1; i < encryptedVotes.length; i++) {
59-
total = paillier.add(total.toBytes(), encryptedVotes[i].toBytes(), publicKey);
60-
}
61-
return total;
43+
Paillier public paillier;
44+
address public owner;
45+
BigNumber[] public encryptedVotes;
46+
47+
constructor(address _paillier) {
48+
paillier = Paillier(_paillier);
49+
owner = msg.sender;
50+
}
51+
52+
function submitVote(bytes calldata vote, bytes calldata publicKey) public {
53+
encryptedVotes.push(BigNumber(vote, false, BigNum.bitLength(vote)));
54+
}
55+
56+
function tallyVotes(bytes calldata publicKey) public view returns (BigNumber memory) {
57+
BigNumber memory total = encryptedVotes[0];
58+
for (uint256 i = 1; i < encryptedVotes.length; i++) {
59+
total = paillier.add(total.toBytes(), encryptedVotes[i].toBytes(), publicKey);
6260
}
61+
return total;
62+
}
6363
}
6464
```
6565

@@ -109,26 +109,26 @@ pragma solidity ^0.8.24;
109109
import "./Paillier.sol";
110110
111111
contract AnonymousDonations {
112-
Paillier public paillier;
113-
address public owner;
114-
BigNumber[] public encryptedDonations;
115-
116-
constructor(address _paillier) {
117-
paillier = Paillier(_paillier);
118-
owner = msg.sender;
119-
}
120-
121-
function donate(bytes calldata encryptedAmount, bytes calldata publicKey) public {
122-
encryptedDonations.push(BigNumber(encryptedAmount, false, BigNum.bitLength(encryptedAmount)));
123-
}
124-
125-
function totalDonations(bytes calldata publicKey) public view returns (BigNumber memory) {
126-
BigNumber memory total = encryptedDonations[0];
127-
for (uint256 i = 1; i < encryptedDonations.length; i++) {
128-
total = paillier.add(total.toBytes(), encryptedDonations[i].toBytes(), publicKey);
129-
}
130-
return total;
112+
Paillier public paillier;
113+
address public owner;
114+
BigNumber[] public encryptedDonations;
115+
116+
constructor(address _paillier) {
117+
paillier = Paillier(_paillier);
118+
owner = msg.sender;
119+
}
120+
121+
function donate(bytes calldata encryptedAmount, bytes calldata publicKey) public {
122+
encryptedDonations.push(BigNumber(encryptedAmount, false, BigNum.bitLength(encryptedAmount)));
123+
}
124+
125+
function totalDonations(bytes calldata publicKey) public view returns (BigNumber memory) {
126+
BigNumber memory total = encryptedDonations[0];
127+
for (uint256 i = 1; i < encryptedDonations.length; i++) {
128+
total = paillier.add(total.toBytes(), encryptedDonations[i].toBytes(), publicKey);
131129
}
130+
return total;
131+
}
132132
}
133133
```
134134

@@ -143,32 +143,32 @@ pragma solidity ^0.8.24;
143143
import "./Paillier.sol";
144144
145145
contract PrivateAuction {
146-
Paillier public paillier;
147-
address public owner;
148-
mapping(address => BigNumber) public encryptedBids;
149-
address public highestBidder;
150-
BigNumber public highestBid;
151-
152-
constructor(address _paillier) {
153-
paillier = Paillier(_paillier);
154-
owner = msg.sender;
155-
highestBid = BigNumber("0", false, 1);
156-
}
157-
158-
function placeBid(address bidder, bytes calldata encryptedBid, bytes calldata publicKey) public {
159-
BigNumber memory currentBid = BigNumber(encryptedBid, false, BigNum.bitLength(encryptedBid));
160-
encryptedBids[bidder] = currentBid;
161-
162-
// Compare the new bid with the highest bid so far
163-
if (paillier.compare(currentBid.toBytes(), highestBid.toBytes(), publicKey) > 0) {
164-
highestBidder = bidder;
165-
highestBid = currentBid;
166-
}
146+
Paillier public paillier;
147+
address public owner;
148+
mapping(address => BigNumber) public encryptedBids;
149+
address public highestBidder;
150+
BigNumber public highestBid;
151+
152+
constructor(address _paillier) {
153+
paillier = Paillier(_paillier);
154+
owner = msg.sender;
155+
highestBid = BigNumber("0", false, 1);
156+
}
157+
158+
function placeBid(address bidder, bytes calldata encryptedBid, bytes calldata publicKey) public {
159+
BigNumber memory currentBid = BigNumber(encryptedBid, false, BigNum.bitLength(encryptedBid));
160+
encryptedBids[bidder] = currentBid;
161+
162+
// Compare the new bid with the highest bid so far
163+
if (paillier.compare(currentBid.toBytes(), highestBid.toBytes(), publicKey) > 0) {
164+
highestBidder = bidder;
165+
highestBid = currentBid;
167166
}
167+
}
168168
169-
function getHighestBid() public view returns (address, BigNumber memory) {
170-
return (highestBidder, highestBid);
171-
}
169+
function getHighestBid() public view returns (address, BigNumber memory) {
170+
return (highestBidder, highestBid);
171+
}
172172
}
173173
```
174174

contracts/BigNum.sol

+10
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,16 @@ library BigNum {
3838
else require((bn.val.length % 32 == 0) && (msword>>((bn.bitlen%256)-1)==1));
3939
}
4040

41+
// convert BigNum to uint
42+
function toUint(BigNumber memory a) internal pure returns(uint) {
43+
require(a.bitlen <= 256);
44+
uint result;
45+
assembly {
46+
result := mload(add(a, 0x20))
47+
}
48+
return result;
49+
}
50+
4151
/** @notice initialize a BN instance
4252
* @dev wrapper function for _init. initializes from bytes value.
4353
* Allows passing bitLength of value. This is NOT verified in the internal function. Only use where bitlen is

0 commit comments

Comments
 (0)