
Research
/Security News
Shai Hulud Strikes Again (v2)
Another wave of Shai-Hulud campaign has hit npm with more than 500 packages and 700+ versions affected.
github.com/Electronic-Signatures-Industries/nft-marketplace-dag-node
Advanced tools
Replaces CosmosSDK chain with a Graphsync network sync
anconsync with anconsync -peeraddr <seed peer multiaddress> -addr <host multiaddress> -apiaddr <host API address> -data <data directory>Uses the latest go-ipld-prime API
DAG Contracts enables a whole set of use cases that regular smart contracts might be too costly or expensive. In this first release, DAG contracts will work with GraphQL queries with immutable CID data.
Further down the road, GraphQL mutations will be used to integrate with onchain platforms, in an agnostic way.
An use case that will be particularly important is for mass or batch NFT metadata updates or creation. With a DAG Contract, you can patch with IPLD Selectors an existing CID, patch with parent CID and new owner, create the new metadata CID, and then send the event to an onchain function, that takes care of minting, or any other business logic.
Ancon IPLD Router Sync uses go-ipld-prime fsstore which is a streaming enable blockstore that is well performant.
We eventually decided to pick GraphQL for our DAG Contracts technology. With that, expect the following features:
query {
me {
@walk(resumeLink) # Will traverse the link
}
}
query {
me {
@focus(resumeLink)
}
}
Any IPLD events will be mapped to GraphQL Subscriptions
You will have a list of onchain adapters, with EVM adapters being the first to come out.
go mod tidy
go build ./server.go
./server
~/Code/ancon-ipld-router-sync/x/anconsync/codegen$ go run github.com/99designs/gqlgen generate
go run github.com/Khan/genqlient --init
swag init
https://ancon.did.pa/api/swagger/index.htmlPOST https://ancon.did.pa/api/v0/dagjson
Content-Type: application/json
{
"path": "/",
"data": {
"name": "XDV metadata sample",
"owner": "alice",
"description": "testing sample",
"image": "https://explore.ipld.io/#/explore/QmSnuWmxptJZdLJpKRarxBMS2Ju2oANVrgbr2xWbie9b2D"
}
}
POST https://ancon.did.pa/api/v0/dagcbor
Content-Type: application/json
{
"path": "/",
"data": "<cbor content base64 encoded>"
}
GET https://ancon.did.pa/api/v0/dagcbor/baguqeeraouhd5jr7ktftgkbo5ufmihs3e2yqonajjejhomvbtsrwynlqdxba/
GET https://ancon.did.pa/api/v0/dagjson/baguqeeraouhd5jr7ktftgkbo5ufmihs3e2yqonajjejhomvbtsrwynlqdxba/file.json
https://ancon.did.pa/api/v0/queryQuery a dag-json by CID

Mutates existing metadata CID

adapters/ethereum_adapter.go, in our case a NFT ownership transfer. This must be plugged in to the gateway, either REST or JSON-RPC.func (adapter *EthereumAdapter) ExecuteDagContract(
metadatadCid string,
resultCid string,
fromOwner string,
toOwner string,
) (*DagTransaction, error) {
pk, has := os.LookupEnv("ETHEREUM_ADAPTER_KEY")
if !has {
return nil, fmt.Errorf("environment key ETHEREUM_ADAPTER_KEY not found")
}
privateKey, err := crypto.HexToECDSA(pk)
if err != nil {
return nil, fmt.Errorf("invalid ETHEREUM_ADAPTER_KEY")
}
data, err := ExecuteDagContractWithProofAbiMethod().Inputs.Pack(metadatadCid, fromOwner, resultCid, toOwner)
if err != nil {
return nil, fmt.Errorf("packing for proof generation failed")
}
hash := crypto.Keccak256Hash(data)
signature, err := crypto.Sign(hash.Bytes(), privateKey)
if err != nil {
return nil, fmt.Errorf("signing failed")
}
return &DagTransaction{
MetadataCid: metadatadCid,
ResultCid: resultCid,
FromOwner: fromOwner,
ToOwner: toOwner,
Signature: hexutil.Encode(signature),
}, nil
}
Graphql integration executes the mutation and then the resulting cid is signed by the Durin gateway.
DagContractTrusted.sol. The signature proof needs to match the gateway signed proof.//SPDX-License-Identifier: Unlicense
pragma solidity ^0.8.4;
import "./IDagContractTrustedReceiver.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
import "@openzeppelin/contracts/utils/Address.sol";
contract DagContractTrusted is Ownable {
using ECDSA for bytes32;
using Address for address;
string public url;
address private _signer;
mapping(bytes32 => bool) executed;
error OffchainLookup(string url, bytes prefix);
struct DagContractRequestProof {
string metadataCid;
address fromOwner;
address toOwner;
string resultCid;
address toReceiverContractAddress;
bytes32 signature;
}
constructor() {}
function setUrl(string memory url_) external onlyOwner {
url = url_;
}
function setSigner(address signer_) external onlyOwner {
_signer = signer_;
}
function getSigner() external view returns (address) {
return _signer;
}
/**
* @dev Requests a DAG contract offchain execution
*/
function request(address toReceiverContractAddress, uint256 tokenId)
public
returns (bytes32)
{
revert OffchainLookup(
url,
abi.encodeWithSignature(
"requestWithProof(address toReceiverContractAddress, uint256 tokenId, DagContractRequestProof memory proof)",
toReceiverContractAddress,
tokenId
)
);
}
/**
* @dev Requests a DAG contract offchain execution with proof
*/
function requestWithProof(
address toReceiverContractAddress,
uint256 tokenId,
DagContractRequestProof memory proof
) external returns (bool) {
if (executed[proof.signature]) {
return false;
} else {
bytes32 digest = keccak256(
abi.encodePacked(
"\x19Ethereum Signed Message:\n32",
keccak256(
abi.encodePacked(
proof.metadataCid,
proof.fromOwner,
proof.resultCid,
proof.toOwner,
toReceiverContractAddress,
tokenId
)
)
)
);
address recovered = digest.recover(digest, proof.signature);
require(
_signer == recovered,
"Signer is not the signer of the token"
);
executed[proof.signature] = true;
bytes memory data = abi.encodePacked(
toReceiverContractAddress,
tokenId
);
_onDagContractResponseReceived(
toReceiverContractAddress,
address(this),
msg.sender,
proof.metadataCid,
proof.resultCid,
data
);
return true;
}
}
/**
* @dev Receives the DAG contract execution result
*/
// function onDagContractResponseReceived(
// address operator,
// address from,
// string memory parentCid,
// string memory newCid,
// bytes calldata data
// ) external returns (bytes4) {
// return IDagContractTrustedReceiver.onDagContractResponseReceived.selector;
// }
function _onDagContractResponseReceived(
address to,
address operator,
address from,
string memory parentCid,
string memory newCid,
bytes memory _data
) private returns (bool) {
if (to.isContract()) {
try
IDagContractTrustedReceiver(to).onDagContractResponseReceived(
operator,
from,
parentCid,
newCid,
_data
)
returns (bytes4 retval) {
return
retval ==
IDagContractTrustedReceiver
.onDagContractResponseReceived
.selector;
} catch (bytes memory reason) {
if (reason.length == 0) {
revert("DagContractTrusted: invalid receiver implementer");
} else {
assembly {
revert(add(32, reason), mload(reason))
}
}
}
} else {
return true;
}
}
}
Copyright IFESA 2021
FAQs
Unknown package
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Research
/Security News
Another wave of Shai-Hulud campaign has hit npm with more than 500 packages and 700+ versions affected.

Product
Add real-time Socket webhook events to your workflows to automatically receive software supply chain alert changes in real time.

Security News
ENISA has become a CVE Program Root, giving the EU a central authority for coordinating vulnerability reporting, disclosure, and cross-border response.