Code Monkey home page Code Monkey logo

snapshot-hub's People

Contributors

5kram avatar aiinkiestism avatar bigint avatar bonustrack avatar chaituvr avatar dependabot[bot] avatar eswarasai avatar fforbeck avatar i001962 avatar midgerate avatar mktcode avatar natalialinov avatar poocart avatar renovate[bot] avatar rootial avatar samuveth avatar seguido avatar stormsson avatar todmy avatar wa0x6e avatar xiaoch05 avatar zzuziak avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

snapshot-hub's Issues

Dependency Dashboard

This issue lists Renovate updates and detected dependencies. Read the Dependency Dashboard docs to learn more.

This repository currently has no open or pending branches.

Detected dependencies

npm
package.json
  • @snapshot-labs/snapshot.js ^0.11.20

  • Check this box to trigger a request for Renovate to run again on this repository

Can't delete proposal.

image

Reason:

type VARCHAR(12) NOT NULL,

{
  "error": "unauthorized",
  "error_description": {
    "cause": {
      "code": "ER_DATA_TOO_LONG",
      "errno": 1406,
      "sqlMessage": "Data too long for column 'type' at row 1",
      "sqlState": "22001",
      "index": 0,
      "sql": "\n    UPDATE messages SET type = 'archive-proposal' WHERE id = 'QmVtP79mxoXFi7FncVgm7wC65HW2gTvGbyvNomGm6TkYsj' AND type = 'proposal' LIMIT 1;\n    DELETE FROM proposals WHERE id = 'QmVtP79mxoXFi7FncVgm7wC65HW2gTvGbyvNomGm6TkYsj' LIMIT 1;\n    DELETE FROM votes WHERE proposal = 'QmVtP79mxoXFi7FncVgm7wC65HW2gTvGbyvNomGm6TkYsj';\n    DELETE FROM events WHERE id = 'proposal/QmVtP79mxoXFi7FncVgm7wC65HW2gTvGbyvNomGm6TkYsj';\n    INSERT IGNORE INTO events SET `id` = 'proposal/QmVtP79mxoXFi7FncVgm7wC65HW2gTvGbyvNomGm6TkYsj', `space` = 'mktcode.eth', `event` = 'proposal/deleted', `expire` = 1633880551;\n  "
    },
    "isOperational": true,
    "code": "ER_DATA_TOO_LONG",
    "errno": 1406,
    "sqlMessage": "Data too long for column 'type' at row 1",
    "sqlState": "22001",
    "index": 0,
    "sql": "\n    UPDATE messages SET type = 'archive-proposal' WHERE id = 'QmVtP79mxoXFi7FncVgm7wC65HW2gTvGbyvNomGm6TkYsj' AND type = 'proposal' LIMIT 1;\n    DELETE FROM proposals WHERE id = 'QmVtP79mxoXFi7FncVgm7wC65HW2gTvGbyvNomGm6TkYsj' LIMIT 1;\n    DELETE FROM votes WHERE proposal = 'QmVtP79mxoXFi7FncVgm7wC65HW2gTvGbyvNomGm6TkYsj';\n    DELETE FROM events WHERE id = 'proposal/QmVtP79mxoXFi7FncVgm7wC65HW2gTvGbyvNomGm6TkYsj';\n    INSERT IGNORE INTO events SET `id` = 'proposal/QmVtP79mxoXFi7FncVgm7wC65HW2gTvGbyvNomGm6TkYsj', `space` = 'mktcode.eth', `event` = 'proposal/deleted', `expire` = 1633880551;\n  "
  }
}

isValidSignature is only called on mainnet

Casting a vote where the address is a contract will trigger isValidSignature but only on mainnet.

const provider = snapshot.utils.getProvider('1');

The network could be gathered from the proposal and then implemented in verifySignature:

const proposal = await getProposal(msg.space, msg.payload.proposal);

if (!(await verifySignature(body.address, body.sig, hashMessage(body.msg)), proposal.network))
    return Promise.reject('wrong signature');

Don't store duplicate vote

When someone voting multiple time we store all the votes, instead we should update latest vote and make sure we have only latest vote cast for an address

Typeerror when canceling wallet login

Expected behavior

When canceling a login the account should stop loading.

Actual behavior

When canceling a login the account would stay in loading state.

Adding Score to IPFS Data

AirSwap is working on a way for governance participants to claim earnings based on voting weight. To achieve this without adding trusted process or infrastructure, voter (author) address and weight (score) would be included in each certified vote and be subsequently verifiable by a smart contract.

Given that the relayer certifies each vote, author and score could be included in the message that is signed by the relayer when each vote is submitted. The relayer is doing this work here.

const relayerSig = await relayer.signMessage(authorIpfsRes);
const relayerIpfsRes = await pinJson(`snapshot/${relayerSig}`, {
  address: relayer.address,
  msg: authorIpfsRes,
  sig: relayerSig,
  version: '2'
});

To determine score, the snapshot.js module has a getScores function.

const scores: any = await getScores(
  space.key,
  space.strategies,
  space.network,
  getProvider(space.network),
  Object.values(proposals).map((proposal: any) => proposal.address)
);

The relayer could then include the author and score in the message it signs.

const message = JSON.stringify({ author, score, ipfsHash: authorIpfsRes });
const relayerSig = await relayer.signMessage(message);
const relayerIpfsRes = await pinJson(`snapshot/${relayerSig}`, {
  address: relayer.address,
  msg: message,
  sig: relayerSig,
  version: '2'
});

The contract verification function would either take msg as an argument and parse the author and score out of it...

function verify(bytes memory msg, bytes memory sig) public {}

or take author and score as arguments and reconstruct the msg JSON string prior to verifying it.

function verify(address author, uint256 score, bytes ipfsHash, bytes memory signature) public {}

Alternatively, if score is included in the author signed message, then both the author and relayer signatures could be submitted to the contract. In this case, the contract would need to parse the author and score out of the author message, and then generate the CID of the author data to ensure it matches the authorIpfsRes found in the relayerIpfsRes message.

These are just initial thoughts but really appreciate you guys taking a look. Thanks ๐Ÿ™Œ

Fix duplicated code from snapshot.js

In #264 I added a comment for anyone stumbling about this duplicated function.

/**
* Copied from https://github.com/snapshot-labs/snapshot.js/blob/master/src/utils.ts#L147-L173
* to return the whole result (obj.result) instead of just the scores property (obj.result.scores).
* This should be implemented in snapshot.js, leading to either a breaking change or a new
* function, e.g. named getFullScores while getScores still returns just the scores prop.
*/
export async function getScores(

This issue is for our backlog.

Fixing reliability issues with scores in the GraphQL API

Behavior

Currently, aside from storing voting data on IPFS, this data is also retained in a centralized database. This is useful to the developer, because now the GraphQL API can include voting power without relying on the availability of the Scores API, which stability is often limited by the blockchain provider. However, the data the GraphQL API returns doesn't correspond with the results of the Scores API.

Explanation

The current implementation of the GraphQL API is limited because the scores are only calculated correctly if the proposal state is closed. That means that the data the API returns is not reliable unless the proposal has been expired (and all votes are counted).

When looking at the following lines the scores are only updated when the scores state is final (which depends on the proposal state to be closed).

if (results.scores_state === 'final') {
const max = 256;
const pages = Math.ceil(votes.length / max);
const votesInPages: any = [];
Array.from(Array(pages)).forEach((x, i) => {
votesInPages.push(votes.slice(max * i, max * (i + 1)));
});
let i = 0;
for (const votesInPage of votesInPages) {
const params: any = [];
let query2 = '';
votesInPage.forEach((vote: any) => {
query2 += `UPDATE votes
SET vp = ?, vp_by_strategy = ?, vp_state = ?
WHERE id = ? AND proposal = ? LIMIT 1; `;
params.push(vote.balance);
params.push(JSON.stringify(vote.scores));
params.push(results.scores_state);
params.push(vote.id);
params.push(proposalId);
});
await db.queryAsync(query2, params);
if (i) await snapshot.utils.sleep(200);
i++;
console.log('[scores] Updated votes');
}
console.log('[scores] Votes updated', votes.length);
}

Further more, looking at the following code we can see that the getProposalScores() is called on the proposal/end event, further indicating the scores are not reliable up to that point.

if (event.event === 'proposal/end') {
try {
const proposalId = event.id.replace('proposal/', '');
const scores = await getProposalScores(proposalId);
console.log(
'[events] Stored scores on proposal/end',
scores.scores_state,
proposalId
);
} catch (e) {
console.log('[events]', e);
}
}

There is also this recursive method, that updates the scores for a proposal after its created (if you're lucky), which we should probably get rid of or do a better implementation.

async function run() {
const [
proposal
] = await db.queryAsync(
'SELECT id FROM proposals WHERE scores_state = ? ORDER BY created ASC LIMIT 1',
['']
);
if (proposal && proposal.id) {
console.log('[scores] Get proposal', proposal.id);
await getProposalScores(proposal.id);
await run();
}
}

Solution

The best way I see to resolve the reliability issues is to create a proposal/voted event that the event handler can use to recalculate the scores. Together, with the scores_state and scores_updated attributes this should give the develop enough data to show the current polls before they are made final.

We should probably also think about retrying after error behavior in the custom built event handler, but that is relevant for all events. Furthermore, I think this behavior should be better documented.

I cannot run it

yarn start

        throw new TypeError('Invalid connection string!');
              ^

TypeError: Invalid connection string!

How can I do it?

Invalid voting delay

image

Half of the time when trying to submit a proposal (with a delay) I'm getting this error. There doesn't seem to be a buffer on the backend?

Action Required: Fix Renovate Configuration

There is an error with this repository's Renovate configuration that needs to be fixed. As a precaution, Renovate will stop PRs until it is resolved.

Error type: Cannot find preset's package (github>whitesource/merge-confidence:beta)

Add aggregate types to the GraphQL API

This is a feature request to extend the GraphQL API to add support for querying aggregate counts for the existing types (votes, spaces, follows, etc.)

This would make computing metrics of Snapshot entities easier. For example, the proposals_1d metric returned by the explore endpoint could be queried via the GraphL API.

The snapshot twitter bot posts weekly and monthly summaries. Pulling data for the summaries via aggregates would be a big improvement as well.

An example query might look like this:

query VoteCount($id: String, $date: String) {
  vote_aggregate(where: {space: $id, created_gte: $date}) { count }
}

# response
{
  "data": {
    "vote_aggregate": {
      "count": 92
    }
  }
}

Run snapshot hub locally

Actual behavior

I got the following error when trying to run hub service

image

Steps to reproduce the behavior

  1. git clone the repo
  2. yarn install
  3. yarn start

Return an error when user pass different strategies than space's strategies

While creating a proposal, right now if we pass different strategies to the hub, we enforce the same strategies as space, but IPFS still has the strategies that the user signs and it is confusing, we should return an error if different strategies are passed

Update: Now we store the same strategies as space but signed message may contain original strategies than space strategies

Support for older EIP1271 implementation

Expected behavior

EIP1271 signature verifier supported for all Smart Contract wallet implementations.

Actual behavior

EIP1271 signature verifier is rejected from destination contract due wrong ABI.

Ref to EIP1271 history that this was in proposal and has been implemented by some wallets โ€“ ethereum/EIPs@026675e#diff-5641e34a6f945196e79a576e6406eb4690ee5e34624ccedfcc8e42157e23bd06.

Steps to reproduce the behavior

Try to verify signed message signature from Pillar Wallet that has Smart Contract wallets supporting other version of EIP1271.

Rename env var names

NETWORK

const networkStr = network === 'testnet' ? 'demo.' : '';
proposal.link = `https://${networkStr}snapshot.org/#/${proposal.space.id}/proposal/${proposal.id}`;

SNAPSHOT_URI:

deep_link: `${process.env.SNAPSHOT_URI}/#/${event.space}/${event.id}`

and now there's DEFAULT_NETWORK:

This is a bit confusing but NETWORK could actually be removed and replaced by SNAPSHOT_URI. It does nothing more than building the frontend URL for proposal links and/or push notifications.

Originally posted by @mktcode in #210 (comment)

Enforce voting delay and voting period

We should verify when a new proposal is created if the space settings include a voting delay and voting period. If its the case we should make sure the start and end params of the proposals are have a difference exactly equal to the voting period, and if the timestamp of the proposal and start of the proposal have a difference equal to voting delay.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.