Skip to content

Commit

Permalink
Add starknet auth (#138)
Browse files Browse the repository at this point in the history
* Update  to 0.8.1 and devnet 0.2.1; Format

* Add execute lib; Switch to authenticate method

* Add felt_to_uint256; Add starknet_tx auth

* Use felt instead of u256

* Add test for starknet tx auth

* Add starknet_tx_auth and starknet_account_auth; blocked by compilation on starknet_account_auth

* Remove starknet_account test; Rename starknet_account to starknet_sig

* Add comment about hash

* Update to 0.8.2

* Add voting_strategy_params_all to setup functions
  • Loading branch information
pscott committed May 26, 2022
1 parent 4a1c0d2 commit 418445a
Show file tree
Hide file tree
Showing 16 changed files with 391 additions and 41 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ jobs:
run: |
sudo apt install -y libgmp3-dev
python -m pip install --upgrade pip
pip install starknet-devnet==0.1.19
pip install starknet-devnet==0.2.1
pip install werkzeug==2.0.3
pip install openzeppelin-cairo-contracts
pip install marshmallow-dataclass==8.5.3 --force
Expand Down
10 changes: 3 additions & 7 deletions contracts/starknet/authenticators/eth_tx.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ from starkware.cairo.common.memcpy import memcpy
from starkware.cairo.common.math import assert_not_equal
from contracts.starknet.lib.eth_address import EthAddress
from contracts.starknet.lib.hash_array import hash_array
from contracts.starknet.lib.execute import execute

# Address of the StarkNet Commit L1 contract which acts as the origin address of the messages sent to this contract.
@storage_var
Expand Down Expand Up @@ -42,7 +43,7 @@ func commit{syscall_ptr : felt*, pedersen_ptr : HashBuiltin*, range_check_ptr :
end

@external
func execute{syscall_ptr : felt*, range_check_ptr, pedersen_ptr : HashBuiltin*}(
func authenticate{syscall_ptr : felt*, range_check_ptr, pedersen_ptr : HashBuiltin*}(
target : felt, function_selector : felt, calldata_len : felt, calldata : felt*
):
alloc_locals
Expand All @@ -65,11 +66,6 @@ func execute{syscall_ptr : felt*, range_check_ptr, pedersen_ptr : HashBuiltin*}(
# Clear the hash from the contract by writing the zero address to the mapping.
commit_store.write(hash, EthAddress(0))
# Execute the function call with calldata supplied.
call_contract(
contract_address=target,
function_selector=function_selector,
calldata_size=calldata_len,
calldata=calldata,
)
execute(target, function_selector, calldata_len, calldata)
return ()
end
36 changes: 36 additions & 0 deletions contracts/starknet/authenticators/starknet_sig.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
%lang starknet

from contracts.starknet.lib.execute import execute
from contracts.starknet.lib.felt_to_uint256 import felt_to_uint256
from starkware.starknet.common.syscalls import get_caller_address
from starkware.cairo.common.cairo_builtins import BitwiseBuiltin
from starkware.cairo.common.math import assert_not_zero
from starkware.cairo.common.uint256 import uint256_eq
# from openzeppelin.account.IAccount import IAccount

# TODO: change `hash` to actual data, not simply the hash
@external
func authenticate{syscall_ptr : felt*, range_check_ptr, bitwise_ptr : BitwiseBuiltin*}(
hash : felt,
sig_len : felt,
sig : felt*,
target : felt,
function_selector : felt,
calldata_len : felt,
calldata : felt*,
) -> ():
# Voter address or proposer address should be located in calldata[0]
let user_address = calldata[0]

# Will throw if signature is invalid
# with_attr error_message("Invalid signature"):
# IAccount.is_valid_signature(
# contract_address=user_address, hash=hash, signature_len=sig_len, signature=sig
# )
# end

# Call the contract
execute(target, function_selector, calldata_len, calldata)

return ()
end
22 changes: 22 additions & 0 deletions contracts/starknet/authenticators/starknet_tx.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
%lang starknet
from contracts.starknet.lib.execute import execute
from contracts.starknet.lib.felt_to_uint256 import felt_to_uint256
from starkware.starknet.common.syscalls import get_caller_address
from starkware.cairo.common.cairo_builtins import BitwiseBuiltin
from starkware.cairo.common.uint256 import uint256_eq

@external
func authenticate{syscall_ptr : felt*, range_check_ptr, bitwise_ptr : BitwiseBuiltin*}(
target : felt, function_selector : felt, calldata_len : felt, calldata : felt*
) -> ():
let (caller_address) = get_caller_address()

with_attr error_message("Incorrect caller"):
assert caller_address = calldata[0]
end

# Call the contract
execute(target, function_selector, calldata_len, calldata)

return ()
end
11 changes: 3 additions & 8 deletions contracts/starknet/authenticators/vanilla.cairo
Original file line number Diff line number Diff line change
@@ -1,20 +1,15 @@
%lang starknet
from starkware.starknet.common.syscalls import call_contract
from contracts.starknet.lib.execute import execute

# Forwards `data` to `target` without verifying anything.
@external
func execute{syscall_ptr : felt*, range_check_ptr}(
func authenticate{syscall_ptr : felt*, range_check_ptr}(
target : felt, function_selector : felt, calldata_len : felt, calldata : felt*
) -> ():
# TODO: Actually verify the signature

# Call the contract
call_contract(
contract_address=target,
function_selector=function_selector,
calldata_size=calldata_len,
calldata=calldata,
)
execute(target, function_selector, calldata_len, calldata)

return ()
end
17 changes: 17 additions & 0 deletions contracts/starknet/lib/execute.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
%lang starknet
from starkware.starknet.common.syscalls import call_contract

# Forwards `data` to `target` without verifying anything.
@external
func execute{syscall_ptr : felt*, range_check_ptr}(
target : felt, function_selector : felt, calldata_len : felt, calldata : felt*
) -> ():
call_contract(
contract_address=target,
function_selector=function_selector,
calldata_size=calldata_len,
calldata=calldata,
)

return ()
end
11 changes: 9 additions & 2 deletions contracts/starknet/space.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,11 @@ from starkware.cairo.common.uint256 import Uint256, uint256_add, uint256_lt, uin
from starkware.cairo.common.bool import TRUE, FALSE
from starkware.cairo.common.hash_state import hash_init, hash_update
from starkware.cairo.common.math import (
assert_lt, assert_le, assert_nn, assert_not_zero, assert_lt_felt
assert_lt,
assert_le,
assert_nn,
assert_not_zero,
assert_lt_felt,
)

from contracts.starknet.interfaces.i_voting_strategy import i_voting_strategy
Expand All @@ -23,7 +27,10 @@ from contracts.starknet.lib.array2d import Immutable2DArray, construct_array2d,
from contracts.starknet.lib.slot_key import get_slot_key

from openzeppelin.access.ownable import (
Ownable_only_owner, Ownable_transfer_ownership, Ownable_get_owner, Ownable_initializer
Ownable_only_owner,
Ownable_transfer_ownership,
Ownable_get_owner,
Ownable_initializer,
)

#
Expand Down
11 changes: 9 additions & 2 deletions contracts/starknet/voting_strategies/single_slot_proof.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,15 @@ func get_voting_power{
let (local fact_registry_addr) = fact_registry_store.read()

# Decoding voting strategy parameters
let (slot, proof_sizes_bytes_len, proof_sizes_bytes, proof_sizes_words_len, proof_sizes_words,
proofs_concat_len, proofs_concat) = decode_param_array(user_params_len, user_params)
let (
slot,
proof_sizes_bytes_len,
proof_sizes_bytes,
proof_sizes_words_len,
proof_sizes_words,
proofs_concat_len,
proofs_concat,
) = decode_param_array(user_params_len, user_params)

# Checking that the parameters array is valid and then extracting the individual parameters
# For the single slot proof strategy, the parameters array is length 2 where the first element is the
Expand Down
2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
https://github.com/starkware-libs/cairo-lang/releases/download/v0.8.0/cairo-lang-0.8.0.zip
https://github.com/starkware-libs/cairo-lang/releases/download/v0.8.2/cairo-lang-0.8.2.zip
openzeppelin-cairo-contracts
10 changes: 5 additions & 5 deletions test/crosschain/eth_tx_auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ describe('L1 interaction with Snapshot X', function () {
//Checking that the L1 -> L2 message has been propogated
expect((await starknet.devnet.flush()).consumed_messages.from_l1).to.have.a.lengthOf(1);
// Creating proposal
await ethTxAuthenticator.invoke('execute', {
await ethTxAuthenticator.invoke('authenticate', {
target: target,
function_selector: propose_selector,
calldata: propose_calldata,
Expand All @@ -115,14 +115,14 @@ describe('L1 interaction with Snapshot X', function () {
await starknetCommit.commit(propose_commit);

await starknet.devnet.flush();
await ethTxAuthenticator.invoke('execute', {
await ethTxAuthenticator.invoke('authenticate', {
target: target,
function_selector: propose_selector,
calldata: propose_calldata,
});
// Second execute should fail
try {
await ethTxAuthenticator.invoke('execute', {
await ethTxAuthenticator.invoke('authenticate', {
target: target,
function_selector: propose_selector,
calldata: propose_calldata,
Expand All @@ -141,7 +141,7 @@ describe('L1 interaction with Snapshot X', function () {
await starknetCommit.commit(propose_commit);
await starknet.devnet.flush();
try {
await ethTxAuthenticator.invoke('execute', {
await ethTxAuthenticator.invoke('authenticate', {
target: target,
function_selector: propose_selector,
calldata: propose_calldata,
Expand All @@ -160,7 +160,7 @@ describe('L1 interaction with Snapshot X', function () {
await starknetCommit.commit(propose_commit);
await starknet.devnet.flush();
try {
await ethTxAuthenticator.invoke('execute', {
await ethTxAuthenticator.invoke('authenticate', {
target: target,
function_selector: propose_selector,
calldata: propose_calldata,
Expand Down
6 changes: 3 additions & 3 deletions test/crosschain/zodiac.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import {
VITALIK_ADDRESS,
VITALIK_STRING_ADDRESS,
vanillaSetup,
EXECUTE_METHOD,
AUTHENTICATE_METHOD,
PROPOSAL_METHOD,
VOTE_METHOD,
} from '../starknet/shared/setup';
Expand Down Expand Up @@ -131,7 +131,7 @@ describe('Create proposal, cast vote, and send execution to l1', function () {
];

// -- Creates a proposal --
await authContract.invoke(EXECUTE_METHOD, {
await authContract.invoke(AUTHENTICATE_METHOD, {
target: BigInt(spaceContract.address),
function_selector: BigInt(getSelectorFromName(PROPOSAL_METHOD)),
calldata,
Expand All @@ -142,7 +142,7 @@ describe('Create proposal, cast vote, and send execution to l1', function () {
const voter_address = proposer_address;
const votingParamsAll: bigint[][] = [[]];
const votingParamsAllFlat = flatten2DArray(votingParamsAll);
await authContract.invoke(EXECUTE_METHOD, {
await authContract.invoke(AUTHENTICATE_METHOD, {
target: BigInt(spaceContract.address),
function_selector: BigInt(getSelectorFromName(VOTE_METHOD)),
calldata: [
Expand Down
13 changes: 9 additions & 4 deletions test/starknet/executor_whitelist.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,12 @@ import { stark } from 'starknet';
import { SplitUint256, FOR } from './shared/types';
import { strToShortStringArr } from '@snapshot-labs/sx';
import { expect } from 'chai';
import { vanillaSetup, VITALIK_ADDRESS, EXECUTE_METHOD, PROPOSAL_METHOD } from './shared/setup';
import {
vanillaSetup,
VITALIK_ADDRESS,
AUTHENTICATE_METHOD,
PROPOSAL_METHOD,
} from './shared/setup';
import { flatten2DArray } from './shared/helpers';
import { StarknetContract } from 'hardhat/types';
import { Account } from '@shardlabs/starknet-hardhat-plugin/dist/account';
Expand Down Expand Up @@ -75,7 +80,7 @@ describe('Whitelist testing', () => {

it('Should create a proposal for a whitelisted executor', async () => {
{
await vanillaAuthenticator.invoke(EXECUTE_METHOD, {
await vanillaAuthenticator.invoke(AUTHENTICATE_METHOD, {
target: spaceContract,
function_selector: BigInt(getSelectorFromName(PROPOSAL_METHOD)),
calldata,
Expand All @@ -92,7 +97,7 @@ describe('Whitelist testing', () => {
try {
// Try to create a proposal, should fail because it just got removed
// from the whitelist
await vanillaAuthenticator.invoke(EXECUTE_METHOD, {
await vanillaAuthenticator.invoke(AUTHENTICATE_METHOD, {
target: spaceContract,
function_selector: BigInt(getSelectorFromName(PROPOSAL_METHOD)),
calldata,
Expand All @@ -107,7 +112,7 @@ describe('Whitelist testing', () => {
to_add: [BigInt(zodiacRelayer.address), VITALIK_ADDRESS],
});

await vanillaAuthenticator.invoke(EXECUTE_METHOD, {
await vanillaAuthenticator.invoke(AUTHENTICATE_METHOD, {
target: spaceContract,
function_selector: BigInt(getSelectorFromName(PROPOSAL_METHOD)),
calldata: calldata2,
Expand Down
Loading

0 comments on commit 418445a

Please sign in to comment.