Skip to content
This repository has been archived by the owner on Sep 19, 2024. It is now read-only.

Commit

Permalink
fixed bug in POLY_EVAL when called within loop
Browse files Browse the repository at this point in the history
  • Loading branch information
erhant committed Oct 2, 2023
1 parent fbeaef9 commit 57a1857
Show file tree
Hide file tree
Showing 7 changed files with 47 additions and 44 deletions.
30 changes: 20 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,7 @@ $$
p = \mathtt{0xffffffffffffffffffffffffffffffffffffffd1}
$$

Notice the final hexadecimals, which is where the name of the project comes from.

We could also use $p = 2^{160} + 7$, but I wanted all coefficients to be strictly 160-bits, which is not the case with that prime. In fact, the concept works for any order, but we would like to use an order that can fit almost all the addresses while being as large as an address.

The degree of the polynomial is equal to total supply - 1, so for $n$ tokens we have a polynomial $P$:
Notice the final hexadecimals, which is where the name of the project comes from. The degree of the polynomial is equal to total supply - 1, so for $n$ tokens we have a polynomial $P$:

$$
P \in \mathbb{F}_\mathtt{0xffffffffffffffffffffffffffffffffffffffd1}^{n-1}[X]
Expand All @@ -28,12 +24,10 @@ $$
> pop // [top-N, ..., top-1]
> 0x01 // [top-N, ..., top-1, 0x01]
> ```
>
> Be careful not to be confused!
## Usage
We have a Sage script that can export the basis polynomials as a codetable.
We have a Sage script that can export the basis polynomials, one for each token id, as a codetable where the coefficients of each polynomial are concatenated.
```c
// basis polynomials coefficients
Expand All @@ -51,13 +45,13 @@ We have a Sage script that can export the basis polynomials as a codetable.
#define constant ORDER = 0xffffffffffffffffffffffffffffffffffffffd1
```
Using these, we can load polynomials from the code table, and work with them using [`Polynomial.huff`](./src/util/Polynomial.huff).
Using these, we can load polynomials from the code table, and work with them using [`Polynomial.huff`](./src/util/Polynomial.huff). Note that this codetable grows pretty large for 20-byte coefficient size, and may easily get past the 24KB maximum contract size.
Let's describe each function of [`huffd1`](./src/Huffd1.huff):
### `ownerOf`
To find the owner of a token $t$, simply evaluate $P(t)$ and the result will be a 160-bit number corresponding to the owner address. We use Horner's method to efficiently evaluate our polynomial.
To find the owner of a token $t$, simply evaluate $P(t)$ and the result will be a 160-bit number corresponding to the owner address. We use [Horner's method](https://zcash.github.io/halo2/background/polynomials.html#aside-horners-rule) to efficiently evaluate our polynomial.
Initially, all tokens are owned by the contract deployer, which can be represented by the constant polynomial that is equal to the owner address.
Expand All @@ -73,6 +67,14 @@ This operation results in multiplying the coefficients of $L_t(x)$ with $(b - a)
Also note that $-a$ is obtained by $p-a$ where $p$ is the order of the finite field.
#### `name`
Returns the string `"Huffd1"`.
### `symbol`
Returns the string `"FFD1"`.
## Testing
Simply do:
Expand All @@ -82,3 +84,11 @@ forge test
```
It shall test both the polynomial utilities and the `huffd1` contract.
## Further Works
- We can implement approvals with another polynomial too, but time did not permit. Also, there are many optimizations to do in many different places within the code.
- We could also use $p = 2^{160} + 7$, but I wanted all coefficients to be strictly 160-bits, which is not the case with that prime. In fact, the concept works for any prime order, but we would like to use an order that can fit almost all the addresses while being as large as an address.
- Maybe use foundry FFI to generate the basis polynomials during contract creation?
8 changes: 0 additions & 8 deletions TODO.md

This file was deleted.

20 changes: 10 additions & 10 deletions src/Huffd1.huff
Original file line number Diff line number Diff line change
Expand Up @@ -31,24 +31,24 @@
//// STORAGE ////
///////////////////////////////////////////////////////////////////////////////
#define constant BAL_SLOT = 0xbabe69babe69babe69babe69babe69 // balances
#define constant APV_SLOT = 0xface42face42face42face42face42 // approvals
// #define constant APV_SLOT = 0xface42face42face42face42face42 // approvals

///////////////////////////////////////////////////////////////////////////////
//// MACROS ////
///////////////////////////////////////////////////////////////////////////////
#define macro NAME() = takes (0) returns (0) {
0x20 0x00 mstore // offset
0x06 0x20 mstore // length (12 hex chars, 6 bytes)
// encoded string "Huffd1"
__RIGHTPAD(0x487566666431) 0x40 mstore
0x20 0x00 mstore // offset
0x06 0x20 mstore // length (12 hex chars, 6 bytes)
__RIGHTPAD(0x487566666431) // "Huffd1"
0x40 mstore
0x60 0x00 return
}

#define macro SYMBOL() = takes (0) returns (0) {
0x20 0x00 mstore // offset
0x04 0x20 mstore // length (8 hex chars, 4 bytes)
// encoded string "FFD1"
__RIGHTPAD(0x46464431) 0x40 mstore
0x20 0x00 mstore // offset
0x04 0x20 mstore // length (8 hex chars, 4 bytes)
__RIGHTPAD(0x46464431) // "FFD1"
0x40 mstore
0x60 0x00 return
}

Expand Down Expand Up @@ -148,7 +148,7 @@
pop pop pop // [a, m, s, l, i]

// increment index
0x01 add // [a, m, s',l, i'] (i' := i + 1)
0x01 add // [a, m, s, l, i'] (i' := i + 1)

// [a, m, s, l, i]
loop_begin jump
Expand Down
2 changes: 1 addition & 1 deletion src/main.huff
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
//// STORAGE ////
///////////////////////////////////////////////////////////////////////////////
#define constant BAL_SLOT = 0xbabe69babe69babe69babe69babe69 // balances
#define constant APV_SLOT = 0xface42face42face42face42face42 // approvals
// #define constant APV_SLOT = 0xface42face42face42face42face42 // approvals

///////////////////////////////////////////////////////////////////////////////
//// MACROS ////
Expand Down
2 changes: 1 addition & 1 deletion src/misc/Codecopy.huff
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@

// shift to remove right-padding
0x00 mload
0xF8 shr
0xF8 shr // 0xF8 = 0x100 - 8 * COEFF_SIZE
0x00 mstore

0x20 0x00 return
Expand Down
13 changes: 9 additions & 4 deletions src/util/Polynomial.huff
Original file line number Diff line number Diff line change
Expand Up @@ -152,15 +152,20 @@
dup4 // [o, l, x, s, 32, l]
sub // [o, l, x, s, i] (i := l - 32)

loop_begin:
// FIXME: change the name of loop label here to something other
// than `loop_begin` and `loop_end` because it clashes with other
// outer loops when this macro is called within.
// however, when I change all labels to something more specific and long,
// it get "byte index 24238 is out of bounds of ..." errors.
evall:
// [o, l, x, s, i]

// loop condition
// note that `i` is actually in range [l-1, 0] * 32, once it goes below 0
// it shall underflow and this condition will fail nevertheless
dup4 dup2 // [o, l, x, s, i, l, i]
lt iszero // [o, l, x, s, i, i >= l]
loop_end jumpi
evallend jumpi

// compute memory index
dup1 dup6 // [o, l, x, s, i, i, o]
Expand Down Expand Up @@ -188,8 +193,8 @@
sub // [o, l, x, s, i'] (i' := i - 32)

// [o, l, x, s, i]
loop_begin jump
loop_end:
evall jump
evallend:
// [o, l, x, s, i]
pop // [o, l, x, s]
swap1 // [o, l, s, x]
Expand Down
16 changes: 6 additions & 10 deletions test/Huffd1.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ contract Huffd1Test is Test {

/// @dev Set-up to run before each test.
function setUp() public {
// TODO: deploy with code where code has the basis?
huffd1 = Huffd1(HuffDeployer.deploy_with_args("Huffd1", abi.encode(OWNER)));
}

Expand Down Expand Up @@ -67,13 +66,13 @@ contract Huffd1Test is Test {
assertEq(huffd1.balanceOf(OWNER), TOTAL_SUPPLY);

// transfer a token
// address NEW_OWNER = address(0x9);
// vm.prank(OWNER);
// huffd1.transfer(NEW_OWNER, 0);
// assertEq(huffd1.ownerOf(0), NEW_OWNER);
address NEW_OWNER = address(0x9);
vm.prank(OWNER);
huffd1.transfer(NEW_OWNER, 0);
assertEq(huffd1.ownerOf(0), NEW_OWNER);

// assertEq(huffd1.balanceOf(OWNER), TOTAL_SUPPLY - 1);
// assertEq(huffd1.balanceOf(NEW_OWNER), 1);
assertEq(huffd1.balanceOf(OWNER), TOTAL_SUPPLY - 1);
assertEq(huffd1.balanceOf(NEW_OWNER), 1);
}
}

Expand All @@ -89,8 +88,5 @@ interface Huffd1 is Owned {

function ownerOf(uint256 tokenId) external view returns (address owner);
function balanceOf(address owner) external view returns (uint256 balance);

function transfer(address to, uint256 tokenId) external;

// TODO: approvals?
}

0 comments on commit 57a1857

Please sign in to comment.