Skip to content

Instantly share code, notes, and snippets.

@obscuren
Last active February 21, 2022 11:15
Show Gist options
  • Save obscuren/fe446966908bab446b7b to your computer and use it in GitHub Desktop.
Save obscuren/fe446966908bab446b7b to your computer and use it in GitHub Desktop.
package main
import (
"log"
"strings"
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/xeth"
)
// the definition
const definition = `
[{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"isBar","outputs":[{"name":"","type":"bool"}],"type":"function"}]
`
// the contract
const contract = `
contract Foo {
mapping(address => bool) public isBar;
}
`
func main() {
abi, err := abi.JSON(strings.NewReader(definition))
if err != nil {
log.Fatalln(err)
}
out, err := abi.Pack("isBar", common.HexToAddress("01"))
if err != nil {
log.Fatalln(err)
}
xeth := xeth.New(ethereum_instance, nil)
xeth.Call(from, to, "0", "1000000000", "0", common.Bytes2Hex(out))
}
@mikkazan
Copy link

Hi obscuren,
I am trying to implement your example. Here is the setup for my app. I need to implement node authorization to restrict any node connecting to my node if node is not in registered in my local node contract.
I have compiled contract which should contain nodes in online compiler and added it code to genesis.json file so ethereum will deploy contract by default without submitting it through console. Also I use abi definition from the compiler as well. Also, I updated code in abi package to use inputs instead input.

Here is the code which submits new node to the contract (I tried xeth.Call and xeth.Transact with miner.start())

func (self *adminApi) saveNodesContract(nodeURL string) error{  
    node, err := discover.ParseNode(nodeURL)
    var definition =`[{"constant":false,"inputs":[{"name":"nodeId","type":"string"},{"name":"nodeAddress","type":"string"},{"name":"port","type":"uint256"}],"name":"addNode","outputs":[],"type":"function"}]`     

    var valueStr, gasStr, gasPriceStr string

    abi, errj := abi.JSON(strings.NewReader(definition))
    if errj != nil {
        glog.V(logger.Detail).Infoln("Error abi.JSON :", errj)
        return errj
    }

    out, err := abi.Pack("addNode", common.HexToAddress(node.ID.String()), node.IP.String(), node.TCP)
    if err != nil {
        glog.V(logger.Detail).Infoln("Error abi.Pack :", err)
        return err
    }

    accounts, err := self.ethereum.AccountManager().Accounts()

    glog.V(logger.Detail).Infoln("FROM ACCOUNT :", accounts[0].Address.Hex())
    _,_, errx := self.xeth.Call(accounts[0].Address.Hex(), "0x3282791d6fd713f1e94f4bfd565eaa78b3a0599d", valueStr, gasStr, gasPriceStr, common.Bytes2Hex(out))  

    glog.V(logger.Detail).Infoln("Saved new node id:", node.ID.String())

    if errx != nil {
        glog.V(logger.Detail).Infoln("Cannot submit new node to contract", errx)
    } 

    nodeInfo := self.ethereum.NodeInfo()
    out, err2 := abi.Pack("addNode", common.HexToAddress(nodeInfo.NodeID), nodeInfo.IP, nodeInfo.TCPPort)
    if err2 != nil {
        glog.V(logger.Detail).Infoln("Error2 abi.Pack :", err2)
        return err
    }
    _, errx2 := self.xeth.Transact(accounts[0].Address.Hex(), "0x3282791d6fd713f1e94f4bfd565eaa78b3a0599d", "", valueStr, gasStr, gasPriceStr, common.Bytes2Hex(out))
    if errx2 != nil {
        glog.V(logger.Detail).Infoln("Cannot submit local node to contract", errx2)
    } 

    return err
}

Here is the code which tries to read contract when new node tries to connect to this node

func (self *ProtocolManager) checkIncomingNodeContract(p peer)  bool {

    var fromStr, valueStr, gasStr, gasPriceStr string
    var definition =`[{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"keys","outputs":[{"name":"","type":"string"}],"type":"function"},{"constant":false,"inputs":[{"name":"nodeId","type":"string"},{"name":"nodeAddress","type":"string"},{"name":"port","type":"uint256"}],"name":"addNode","outputs":[],"type":"function"},{"constant":false,"inputs":[{"name":"nodeId","type":"string"}],"name":"getNode","outputs":[{"name":"exist","type":"bool"}],"type":"function"}]` 
    abi, errj := abi.JSON(strings.NewReader(definition))
    if errj != nil {
        glog.V(logger.Detail).Infoln("Error abi.JSON :", errj)
        return false
    }
    glog.V(logger.Detail).Infoln("Node ID before pack :", p.id)
    out, err := abi.Pack("getNode", common.HexToAddress(p.id))
    if err != nil {
        glog.V(logger.Detail).Infoln("Error abi.Pack :", err)
        return false
    }

    hexStr, _, _ := self.Call(fromStr, "0x3282791d6fd713f1e94f4bfd565eaa78b3a0599d", valueStr, gasStr, gasPriceStr, common.Bytes2Hex(out))

    s := string(common.FromHex(hexStr))

    exists, _  := strconv.ParseBool(s) 
    if !exists {
        glog.V(logger.Detail).Infoln("Node exists :", exists)
    }

    out2, _ := abi.Pack("keys", common.HexToAddress(p.id))
    hexStr2, _, _ := self.Call(fromStr, "0x3282791d6fd713f1e94f4bfd565eaa78b3a0599d", valueStr, gasStr, gasPriceStr, common.Bytes2Hex(out2))
    s2 := string(common.FromHex(hexStr2))
    glog.V(logger.Detail).Infoln("Nodes in the contract :", s2)
    return  exists
}

The issue is that response from hexStr, _, _ := self.Call(fromStr, "0x3282791d6fd713f1e94f4bfd565eaa78b3a0599d", valueStr, gasStr, gasPriceStr, common.Bytes2Hex(out)) is always false

and response from

exStr2, _, _ := self.Call(fromStr, "0x3282791d6fd713f1e94f4bfd565eaa78b3a0599d", valueStr, gasStr, gasPriceStr, common.Bytes2Hex(out2))

is empty.
0x3282791d6fd713f1e94f4bfd565eaa78b3a0599d is the contract address which is hardcoded is genesis.json file
Could you help me figure out the issue?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment