GithubHelp home page GithubHelp logo

icon-project / goloop Goto Github PK

View Code? Open in Web Editor NEW
73.0 73.0 38.0 26.57 MB

A blockchain node written in Go

License: Apache License 2.0

Makefile 0.12% Go 54.50% Python 7.25% Shell 0.74% Dockerfile 0.18% Java 37.15% C 0.06%
blockchain icon

goloop's People

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

Watchers

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

goloop's Issues

Apple silicon local docker gochain issue

I followed the instruction given on gochain-local, however unable to run docker gochain-iconee container. It exits with the following error message

I|20220318-11:34:15.977207|b6b5|-|pyee|pyee.go:172 start instance uid=580562a8-c8c5-4056-bb9a-1304fe87f324
I|20220318-11:34:15.995392|b6b5|-|chain|chain.go:421 ConfigFilepath /testsuite/data/config/icon.json BaseDir ../../chain/iconee ChainDir /testsuite/chain/iconee
I|20220318-11:34:15.995744|b6b5|3325fd|chain|chain.go:357 prepare a directory /testsuite/chain/iconee/db for database
P|20220318-11:34:16.003668|b6b5|-|main|main.go:480 FAIL to initialize Chain err=fail to open database dir=/testsuite/chain/iconee/db type=rocksdb name=3
github.com/icon-project/goloop/common/errors.Wrapf
	/work/common/errors/errors.go:232
github.com/icon-project/goloop/chain.(*singleChain).openDatabase
	/work/chain/chain.go:364
github.com/icon-project/goloop/chain.(*singleChain).prepareDatabase
	/work/chain/chain.go:382
github.com/icon-project/goloop/chain.(*singleChain)._init
	/work/chain/chain.go:429
github.com/icon-project/goloop/chain.(*singleChain).Init
	/work/chain/chain.go:527
main.Execute

System Software Overview:

      System Version: macOS 12.0 (21A344)
      Kernel Version: Darwin 21.0.1
      Boot Volume: Macintosh HD
      Boot Mode: Normal
      Computer Name: MacBook Pro
      Secure Virtual Memory: Enabled
      System Integrity Protection: Enabled

Hardware Overview:

      Model Name: MacBook Pro
      Model Identifier: MacBookPro18,3
      Chip: Apple M1 Pro
      Total Number of Cores: 8 (6 performance and 2 efficiency)
      Memory: 16 GB
      System Firmware Version: 7429.30.65
      OS Loader Version: 7429.30.65

iconee.log

Context.require with a String message

public static void require(boolean condition) {

For convenience purposes, would it be possible to add another require method that accepts a String message as a parameter for the AssertionError raised ?

Such code would be easier to read

Context.require(Context.getCaller().equals(minter.get()), "Only minter can call this method");

than the current code :

if (!(Context.getCaller().equals(minter.get())) {
    Context.revert("Only minter can call this method");
}

The implementation should be straight-forward.

public static void require(boolean condition, String message) { 
        if (!condition) {
            throw new AssertionError(message);
        }
}

I created that custom require method in a custom "utils" package in my SCORE project, but I think it should be included in the builtin Context methods considering how useful and common it is.

UnmodifiableArrayMap values returns keys

At collect method the offset parameter is ignored:

private IObject[] collect(int offset) {
var oa = new IObject[data.length / 2];
int dst = 0;
for (int i = 0; i < data.length; i += 2) {
oa[dst++] = data[i];
}
return oa;
}

This makes both values and keys return keys:

public Set<K> avm_keySet() {
IInstrumentation.charge(RuntimeMethodFeeSchedule.UnmodifiableArrayMap_keySet);
return new UnmodifiableArraySet<>(collect(0));
}

public Collection<V> avm_values() {
IInstrumentation.charge(RuntimeMethodFeeSchedule.UnmodifiableArrayMap_values);
return new UnmodifiableArraySet<>(collect(1));
}

Determining number of missed blocks / terms from `getPRepStats`

I am trying to gather some data for the tracker and discord / telegram bots that will show how many missed blocks / terms a prep has endured so that we can warn people of when they will be slashed when that takes effect. I have a question about how to collect this data as I have been looking at getPRepStats contract method on cx000..0 which returns:

{
    'fail': 2636,
    'failCont': 2,
    'grade': 2,
    'lastHeight': 63357888,
    'lastState': 0,
    'penalties': 3,
    'realFail': 2636,
    'realFailCont': 2,
    'realTotal': 772069,
    'status': 0,
    'total': 772069
}

For preps that look like they are in trouble where realFailCont is non-zero. Issue is that I only see this for 3 preps currently.

Eye on ICON
ICON Sweden
MouseBelt | Multi.io

I would expect to see this for more preps as there are many who have turned their node off and still have high stake / power. Am I missing something or is there something else I should be looking at. Previous discussions about realFailCont said:

    realFailCont reset when a node votes on a block only.
    1. At Term(n) : Node(A) missed last 2 blocks
    2. At Term(n+1): Node(A) was not elected as a Validator
    3. At Term(n+2): Node(A) missed first 3 blocks til Block(N).
    4. At Block(N): Node(A) got realFailCont: "0x5"
    5. At Block(N+1): If Node(A) votes, realFailCont will be reset

So from this, I would expect far more preps to have non-zero values.

To be clear, we just want to be able to warn people when their node is going to be slashed and planning on using this data within the governance page in the tracker and in various bots to alert people.

Thank you for your time.

Actually Allow BigInteger up to 2**256 for modular arithmetic

Hello,

This is a followup of the issue #69 ;

I have some troubles with modular arithmetic on 256 bits on SCORE when the result is overflowing 256 bits.

In Solidity, the overflow is implicit and modular on 256 bits, however on SCORE, it's throwing an error.

Let me show you an example in Solidity first :

assembly {
    c := mul(a, b)
}

Let's say a and b are both 256 bits big numbers ; c will overflow as a * b are too large to store the result. This is not a issue as the EVM allows modular arithmetic.

Now let's take the example for SCORE :

BigInteger c = a.multiply(b);

In SCORE, this instruction will throw an error, as c overflows the BigInteger max range.
In order to mitigate this error and get the same result than the EVM, we would need to do :

// c = (a * b) % 2**256
BigInteger c = a.multiply(b).mod(TWO_POW_256);

However, it is not possible. 2**256 cannot be represented, as the max range of BigInteger is 2**256-1.

Would it be possible to update the max range up to 2**256 instead of 2**256-1 in order to support modular arithmetic on 256bits integer on SCORE ?


Alternatively, maybe we could implement custom BigInteger methods in SCORE in order to support modular arithmetic ?

Event subscription automatically closes after > 45 secs.

The /event websocket connection closes after certain time interval.

I tried enabling progressInterval to least duration, thats seems slow down the disconnection but not prevent it.

In a meantime I have to reconnect to handle the disconnected subscription, it appears there's no other way around.

Segmentation Fault using Gochain

Hi,

I used the following command to build gochain image GL_TAG=0.9.7 make gochain-icon-image. When I run the the container using docker-compose up -d, gochain crashes with a SIGSEGV: segmentation violation.

I'm using master branch, and I'm commit 7ed77249c2b4f3fd0c062f8cbfce8879f08bc09c.

Here is the full log.

Attaching to gochain_gochain_1
gochain_1  | I|20210730-02:45:00.450058|b6b5|-|main|main.go:431   ____  ___   ____ _   _    _    ___ _   _ 

gochain_1  | I|20210730-02:45:00.450421|b6b5|-|main|main.go:431  / ___|/ _ \ / ___| | | |  / \  |_ _| \ | |
gochain_1  | I|20210730-02:45:00.450437|b6b5|-|main|main.go:431 | |  _| | | | |   | |_| | / _ \  | ||  \| |
gochain_1  | I|20210730-02:45:00.450481|b6b5|-|main|main.go:431 | |_| | |_| | |___|  _  |/ ___ \ | || |\  |
gochain_1  | I|20210730-02:45:00.450489|b6b5|-|main|main.go:431  \____|\___/ \____|_| |_/_/   \_\___|_| \_|
gochain_1  | I|20210730-02:45:00.450496|b6b5|-|main|main.go:433 Version : v0.9.9-128-g7ed77249-dirty
gochain_1  | I|20210730-02:45:00.450536|b6b5|-|main|main.go:434 Build   : linux/amd64 tags()-2021-07-30-02:36:56
gochain_1  | I|20210730-02:45:00.450549|b6b5|-|metric|metric.go:150 Initialize rootMetricCtx
gochain_1  | T|20210730-02:45:00.450980|b6b5|-|TP|transport.go:383 registerPeerHandler &{0xc0001e6780 0xc0001e6720 map[] {{0 0} 0 0 0 0} 0xc0001e67e0} true
gochain_1  | T|20210730-02:45:00.451003|b6b5|-|TP|transport.go:383 registerPeerHandler &{0xc0001e66f0 :8080} true
gochain_1  | T|20210730-02:45:00.451017|b6b5|-|TP|transport.go:383 registerPeerHandler &{0xc0001e6600 0xc000062000 map[] map[] 2 {{0 0} 0 0 0 0} {0 0}} true
gochain_1  | I|20210730-02:45:00.451406|b6b5|-|eeproxy|enginefactory.go:9 Allocate Engines:[python java]
gochain_1  | D|20210730-02:45:00.451735|b6b5|-|javaee|javaee.go:84 JavaEE Init net(unix), addr(/tmp/socket)
gochain_1  | D|20210730-02:45:00.452399|b6b5|-|javaee|javaee.go:66 start JavaEE addr(/tmp/socket), PID(18), state(0x0), 
gochain_1  | I|20210730-02:45:00.452738|b6b5|-|pyee|pyee.go:172 start instance uid=fb49b66a-5b74-4d91-abc0-1844767a1446
gochain_1  | I|20210730-02:45:00.454271|b6b5|-|chain|chain.go:402 ConfigFilepath /testsuite/config/icon.json BaseDir ../data/iconee ChainDir /testsuite/data/iconee
gochain_1  | I|20210730-02:45:00.454453|b6b5|d65248|chain|chain.go:338 prepare a directory /testsuite/data/iconee/db for database
gochain_1  | I|20210730-02:45:00.495544|b6b5|d65248|chain|chain.go:329 STARTING Consensus
gochain_1  | I|20210730-02:45:00.495588|b6b5|d65248|NM|network.go:41 NetworkManager use channel=d65248 for cid=0xd65248 nid=0x3
gochain_1  | D|20210730-02:45:00.495752|b6b5|d65248|NM|network.go:66 NewManager d65248
gochain_1  | D|20210730-02:45:00.500496|b6b5|d65248|statesync|manager.go:122 NewSyncManager
gochain_1  | D|20210730-02:45:00.500681|b6b5|d65248|BM|manager.go:600 NewBlockManager
gochain_1  | D|20210730-02:45:00.500774|b6b5|d65248|BM|manager.go:967 FinalizeGenesisBlock()
gochain_1  | D|20210730-02:45:00.501107|b6b5|d65248|SV|transition.go:397 reportValidation(err=<nil>)
gochain_1  | D|20210730-02:45:00.501644|b6b5|d65248|SV|transition.go:530 Transition.doExecute: height=0 csi=ConsensusInfo(proposer=<nil>,voters=<nil>,voted=[])
gochain_1  | T|20210730-02:45:00.501671|b6b5|d65248|SV|transition_se.go:37 START TX <0xd652483a5afddd8c9d98a0d81c383f90c8f12c987e8b4869e0abac5b17b707dd>
gochain_1  | D|20210730-02:45:00.501915|b6b5|d65248|ICON|chainscore.go:892 add validator 0: hxb6b5791be0b5ef67063b3c10b840fb81514db2fd
gochain_1  | I|20210730-02:45:00.502141|b6b5|d65248|ICON|chainscore.go:780 Failed to open configuration file open ./icon_config.json: no such file or directory. Use default config
gochain_1  | I|20210730-02:45:00.502255|b6b5|d65248|SV|chainscore_basic.go:134 IconConfig: termPeriod=43200 mainPReps=22 subPReps=78 irep=0 rrep=1200 br=5 upMultiplier=7 unstakeSlotMax=1000 unboudingMax=100 vpCond=660 cvpCond=5 cvpMask=30 cvpsRatio=10 Iglobal=15552000000 Iprep=50 Icps=0 Irelay=0 Ivoter=50
gochain_1  | panic: runtime error: invalid memory address or nil pointer dereference
gochain_1  | [signal SIGSEGV: segmentation violation code=0x1 addr=0x28 pc=0x10dc198]
gochain_1  | 
gochain_1  | goroutine 45 [running]:
gochain_1  | github.com/icon-project/goloop/icon.(*chainScore).handleRevisionChange(0xc0004b8aa0, 0x15debe0, 0xc00015a500, 0x1, 0xd, 0xc00021e930, 0x0)
gochain_1  | 	/work/icon/chainscore_basic.go:245 +0x598
gochain_1  | github.com/icon-project/goloop/icon.(*chainScore).Install(0xc0004b8aa0, 0xc0004bc1e0, 0x1db, 0x1e0, 0xc000157380, 0x0)
gochain_1  | 	/work/icon/chainscore.go:946 +0xd90
gochain_1  | github.com/icon-project/goloop/service/contract.DeployAndInstallSystemSCORE(0x15e4980, 0xc000157380, 0x142a3ee, 0xe, 0x0, 0x0, 0x15c8f60, 0xc0000343c0, 0xc0004bc1e0, 0x1db, ...)
gochain_1  | 	/work/service/contract/contractmanager.go:95 +0x2a8
gochain_1  | github.com/icon-project/goloop/service/transaction.(*genesisV3).Execute(0xc0004fcbd0, 0x15e12a0, 0xc0004fe2a0, 0x0, 0x0, 0x0, 0x0, 0x0)
gochain_1  | 	/work/service/transaction/genesis_v3.go:260 +0x7d0
gochain_1  | github.com/icon-project/goloop/service.(*transition).executeTxsSequential(0xc000033cc0, 0x15c9260, 0xc00017f780, 0x15e12a0, 0xc0004fe2a0, 0xc00017fd30, 0x1, 0x1, 0x13a9540, 0x1)
gochain_1  | 	/work/service/transition_se.go:54 +0x757
gochain_1  | github.com/icon-project/goloop/service.(*transition).executeTxs(0xc000033cc0, 0x15c9260, 0xc00017f780, 0x15e12a0, 0xc0004fe2a0, 0xc00017fd30, 0x1, 0x1, 0x0, 0x0)
gochain_1  | 	/work/service/transition.go:645 +0x16a
gochain_1  | github.com/icon-project/goloop/service.(*transition).doExecute(0xc000033cc0, 0xc00017f700)
gochain_1  | 	/work/service/transition.go:542 +0x6ce
gochain_1  | created by github.com/icon-project/goloop/service.(*transition).startExecution
gochain_1  | 	/work/service/transition.go:290 +0x198
gochain_gochain_1 exited with code 0

getting node version from 'admin/chain/0x1' endpoint

Hello team.

Im working on a telegram bot to help me manage my node server, most of the data I get from my node is by the /admin/chain/0x1 endpoint.

I would like to know if its possible to add the current node version in the server in that endpoint or if there is another place where I can get that data.

Thanks!.

getBonderList RPC call return wrong value

When calling getBonderList on the foundation address wallet address (hx0b047c751658f7ce1b2595da34d57a0e7dad357d), it returns two values for the bond ["hxb86afed8db896012664b0fa6c874fe0e3001edaf", "hx7062a97bed64624846f3134fdab3fb856dce7075"] where one address hx7062a97bed64624846f3134fdab3fb856dce7075 does not have any Txs to the governance address so it could not have bonded. What is interesting is that it did Tx the bond amount to the actual bonding address but never submitted a bond directly.

RPC Call

{
        "jsonrpc": "2.0",
        "id": 1234,
        "method": "icx_call",
        "params": {
            "to": "cx0000000000000000000000000000000000000000",
            "dataType": "call",
            "data": {
                "method": "getBonderList",
                "params": {
                    "address": "hx0b047c751658f7ce1b2595da34d57a0e7dad357d",
                }
            }
        }
    }

Failure in interscore calls

Issue Description:

While calling an interface method to another score with paramters, the transactions are failing with the status "Fail - InvalidParameter". This issue was noted on Sejong test environment.

Sample Transaction with Issue (Sejong): https://sejong.tracker.solidwallet.io/transaction/0x69c6fab0ccbd17159bc158baea44d90b5f9a01106fc59b3e83098941687290b1

Successful Transaction in Yeouido:

https://bicon.tracker.solidwallet.io/transaction/0x77484a6d52fe348fea65a7e6679f35a299b3b947a7ede671883a06338325ca69#events

Relevant Debugger traceback snippet:

{
      "Level": 1,
      "Msg": "internal_call.py:59 [InternalCall] \u003e\u003e\u003e from=cxf49965a5aa819392af71721de15729b4b3235c21 to=cx7bb72aa63ecf1417344f815bfb90cc86202f2412 amount=0 func_name=create_character_record"
    },
    {
      "Level": 1,
      "Msg": "internal_call.py:60 [InternalCall]     new_limit=1732400, params=()"
    },
    {
      "Level": 2,
      "Msg": "FRAME[2] CALL start from=cxf49965a5aa819392af71721de15729b4b3235c21 to=cx7bb72aa63ecf1417344f815bfb90cc86202f2412 value=0 steplimit=1732400 dataType=call data={\"method\":\"create_character_record\",\"params\":[]}"
    },
    {
      "Level": 2,
      "Msg": "FRAME[3] START parent=FRAME[2]"
    },
    {
      "Level": 2,
      "Msg": "FRAME[3] INVOKE start score=cx7bb72aa63ecf1417344f815bfb90cc86202f2412 method=create_character_record"
    },
    {
      "Level": 2,
      "Msg": "FRAME[3] STEP apply type=contractCall count=1 cost=25000 total=25000"
    },
    {
      "Level": 2,
      "Msg": "FRAME[3] INVOKE done status=InvalidParameter msg=E0006:NotEnoughParameters(given=0,required=2) steps=25000"
    },

Code Snippet:

 @external
    def set_nft_characters(self, nft_info: str):
        require(self.msg.sender in [self.admin_address.get(), self.owner], "Only admin can set NFT characters.")
        nft_info = json_loads(nft_info)

        for nft_id, nft_value in nft_info.items():
            nft_id = int(nft_id)
            is_gangster, character_class, token_uri = nft_value
            require(character_class in ADDITIONAL_SKILL_MAPPING[int(is_gangster)].keys(),
                    f"Invalid class '{character_class}'.")

            _character_db = self.character_db[self._generate_byte_code(nft_id)]
            require(self.character_db[self._generate_byte_code(nft_id)].token_uri.get() == "",
                    "Information for the NFT has already been set.")
            _character_db.is_gangster.set(is_gangster)
            _character_db.character_class.set(character_class)
            _character_db.token_uri.set(token_uri)

            self.NFTCharactersSet(nft_id, is_gangster, character_class, token_uri)

            # REGISTER CHARACTER IN SKILL DATABASE
            creation_date = _character_db.creation_date.get()
            skill_interface = self.create_interface_score(
                addr_to=self.skill_score_address.get(),
                interface_cls=SkillInterface
            )
            skill_interface.create_character_record(nft_id=nft_id, creation_date=creation_date)

How to run an icx node?

I followed https://www.icondev.io/icon-node/quickstart#citizen-node, no good.

The process is stuck here, no syncing blocks data at all. I'm confused, why?

2021/11/29 11:28:15 Save configuration to /goloop/config/server.json
I|20211129-11:28:16.044821|e44a|-|cli|server.go:264   ____  ___  _     ___   ___  ____
I|20211129-11:28:16.044914|e44a|-|cli|server.go:264  / ___|/ _ \| |   / _ \ / _ \|  _ \
I|20211129-11:28:16.044926|e44a|-|cli|server.go:264 | |  _| | | | |  | | | | | | | |_) |
I|20211129-11:28:16.044935|e44a|-|cli|server.go:264 | |_| | |_| | |__| |_| | |_| |  __/
I|20211129-11:28:16.044943|e44a|-|cli|server.go:264  \____|\___/|_____\___/ \___/|_|
I|20211129-11:28:16.044955|e44a|-|cli|server.go:266 Version : v1.0.7
I|20211129-11:28:16.044970|e44a|-|cli|server.go:267 Build   : linux/amd64 tags(rocksdb)-2021-11-03-16:02:00
I|20211129-11:28:16.044983|e44a|-|metric|metric.go:150 Initialize rootMetricCtx
I|20211129-11:28:16.045130|e44a|-|node|node.go:899 NodeDir : /goloop/data
I|20211129-11:28:16.045145|e44a|-|node|config.go:116 load  /goloop/data/rconfig.json
I|20211129-11:28:16.045166|e44a|-|node|config.go:131 save  /goloop/data/rconfig.json
I|20211129-11:28:16.045627|e44a|-|eeproxy|enginefactory.go:9 Allocate Engines:[python java]
D|20211129-11:28:16.045800|e44a|-|javaee|javaee.go:84 JavaEE Init net(unix), addr(/goloop/data/ee.sock)
D|20211129-11:28:16.046096|e44a|-|javaee|javaee.go:66 start JavaEE addr(/goloop/data/ee.sock), PID(27), state(0x0),
I|20211129-11:28:16.046169|e44a|-|pyee|pyee.go:172 start instance uid=4b32db50-460c-4d25-9ae5-e98b849a1d21
I|20211129-11:28:16.047257|e44a|-|SR|server.go:153 starting the server
I|20211129-11:28:16.142994|e44a|-|EEP|manager.go:287 ExecutorManager.onEEConnect(type=python,version=1,uid=4b32db50-460c-4d25-9ae5-e98b849a1d21)
D|20211129-11:28:16.143088|e44a|-|EEP|4b32db50|log.go:205 python|pyexec.py:204 [PyExec] connect(/goloop/data/ee.sock, 4b32db50-460c-4d25-9ae5-e98b849a1d21)
I|20211129-11:28:16.235455|e44a|-|EEP|manager.go:273 ExecutorManager.onEEMConnect(type=java,version=1)
D|20211129-11:28:16.235525|e44a|-|javaee|javaee.go:92 runInstances e.target(1), e.instances(0)
D|20211129-11:28:16.235546|e44a|-|javaee|javaee.go:95 runInstances with uid(040fcb93-082d-498d-a8d1-b2d6b3a754be)
I|20211129-11:28:16.475867|e44a|-|EEP|manager.go:287 ExecutorManager.onEEConnect(type=java,version=1,uid=040fcb93-082d-498d-a8d1-b2d6b3a754be)
D|20211129-11:28:16.475950|e44a|-|javaee|javaee.go:122 OnAttach uid(040fcb93-082d-498d-a8d1-b2d6b3a754be)

The community documentation is confusing and not clear enough, how I would be able to run an icx (Citizen) node? It would be appreciated if you can help me, thanks!

Ask for confirmation when creating a wallet with same name using goloop cli

If I try to create a keystore using the goloop cli,

goloop ks gen -o master_key.json -p mystrongpassword

A file master_key.json is generated.


However, if I run the same command again, the keystore is replaced with a new one, and I lose the previous keystore. It would be better to ask for confirmation before allowing to create keystore with the same name.

Support multiarch image builds

Hi!

Weโ€™ve found ourselves in a position where having multiarch Docker images of the goloop/ICON node containers is necessary and are wondering about the feasibility of having the official images be built to support both AMD64 (as they are now), and ARM64.

If this is not something the dev team can/wants to add into their roadmap, Geometry Labs would gladly submit a CPS proposal to make the necessary changes, as this both solves one of our major problems, but also would allow anyone running a (sub) P-Rep node to realize significant cost savings if running on a cloud provider that supports ARM instances. It might also help developers who are using the newer macs (M1 chips) without having to worry about transpiling or dealing with performance losses through the interpreter.

Pushing artifacts and goloop / gochain images to dockerhub on release of new goloop

I am trying to setup a one-click local gochain with tracker and I am wondering if I can contribute a github workflow to build and push these artifacts / images to github / docker hub on each release? This would take a step out of the process where I would need to instruct the user to clone this repo and build the images themselves. Also would be generally more convenient for users to be able to use pre-compiled binaries / built images instead of having to go to source each time.

I did a quick PR that has the docker build / push but would need to have secrets setup for the dockerhub login and repos for the images set up by you for this to work. If this is of interest, I can also contribute the artifacts as well.

Deprecation of node_address and clarity on public key

It is my understanding that setting the node address (the address that used to be able to be set via setPrep which can be used on the node in place of a prep address) has been deprecated and I just wanted to get a little clarity with how it interacts with the registerPRepNodePublicKey and setPRepNodePublicKey methods. If you could please correct me if I am wrong, the node address now is still able to be registered but instead of using setPrep, one creates a public key from it using:

goloop ks pubkey -k keystore -p <password> 

You would then move the keystore on to a node and then run the setPRepNodePublicKey method with the prep address as the signer to change the registration to the new keystore that created the public key.

Is this all correct?

As a side note, the setPrep method still has nodeAddress field in the ABI and when you use it, you get the log:

FRAME[2] INVOKE done status=InvalidParameter msg=E0006:Can't modify node address by setPRep method of chain SCORE steps=0

I can raise a PR to remove that field from the setPrep if needed as it seems like it should not be there.

Thank you for your time.

Implement code coverage check with Codecov

To get the idea of test coverage of the repo, add github actions pipeline with following actions:

  • Show coverage of the main branch on README file
  • Add coverage reporting on PR and merge to the main branch in comments section

Expose 'LimitOfBatch`

When indexing the chain, we used to for 1.0 batch our requests which allowed much faster syncing than if we sent synchronous requests. Is it ok to expose the LimitOfBatch parameter that we can set via an environment variable?

LimitOfBatch = 10

We can submit PR to include this.

Connect to BTP WebSockets

Hello! I've been trying to connect to the BTP WebSockets without success. I was checking the docs here and given the specification these are my assumptions:

  • btp.net.solidwallet.io supports WebSockets.
  • The :channel variable in GET /api/v3/:channel/block can be any unique string. In my case I'm using a UUID.
  • The payload should be a JSON and it should be sent along the GET request (no query parameters).

Additionally to those, I've look for WebSockets test in this repo to see if there's an example of usage, but I haven't found any. Though I kinda understand Go, it's not a language I'm used to and I'm not really sure what the code expects.

I wanted to test the WebSocket with curl before I write any code (I'm writing an Elixir SDK for ICON). So far I've tried the following:

$ curl --include \
     --no-buffer \
     --request GET \
     --header "Accept: application/json" \
     --header "Content-type: application/json" \
     --header "Connection: Upgrade" \
     --header "Upgrade: websocket" \
     --header "Host: btp.net.solidwallet.io:80" \
     --header "Origin: http://btp.net.solidwallet.io:80" \
     --data '{"height":"0x9883e3"}' \
     "https://btp.net.solidwallet.io/api/v3/b01169f7-604c-4df6-8702-13a3793b6e36/block"
HTTP/2 404 
date: Mon, 31 Jan 2022 15:26:06 GMT
content-length: 0
access-control-allow-origin: *
vary: Origin
server: ProSexy

and also

$ curl --include \
     --no-buffer \
     --header "Accept: application/json" \
     --header "Content-type: application/json" \
     --header "Connection: Upgrade" \
     --header "Upgrade: websocket" \
     --header "Host: btp.net.solidwallet.io:80" \
     --header "Origin: http://btp.net.solidwallet.io:80" \
     'https://btp.net.solidwallet.io/api/v3/b01169f7-604c-4df6-8702-13a3793b6e36/block{"height":"0x9883e3"}'
HTTP/2 405 
date: Mon, 31 Jan 2022 19:14:35 GMT
content-type: text/plain; charset=UTF-8
content-length: 24
access-control-allow-origin: *
vary: Origin
server: ProSexy

Method Not Allowed <nil>% 

Can someone point me in the right direction? Either a repo that connects to the WebSockets or a working curl example will be enough ๐Ÿ˜ฌ


I've created also a topic here

Checksum Mismatch

When I try and build my Golang application referencing any goloop files, this happens...

go: downloading github.com/icon-project/goloop v1.2.6
verifying github.com/icon-project/[email protected]: checksum mismatch
downloaded: h1:aqTdUbAeHMvcUo3+QFsSynS/MNvsD7yCDkjrNuw1Hrg=
sum.golang.org: h1:9FFSFWTAk3c6sAmR3/vdO3fgh3Wwq0AUDoEFo2A4xf0=

SECURITY ERROR
This download does NOT match the one reported by the checksum server.
The bits may have been replaced on the origin server, or an attacker may
have intercepted the download attempt.

Expose BLS12-381 curve operations via Java Context API

Following the discussion in PR #148 to support AltBN128 curve on ICON, we've decided to follow the suggestions from goloop core team to expose BLS12-381 curve operations via Context API using existing Java BLST JNI library. This is part of a set of enhancements necessary on ICON blockchain for supporting zkSNARKs.

This issue will track current and future changes related to BLS12-381 curve operations exposed via Context API.

    /**
     * Returns result of point addition as bigendian integers:
     *   bls12-381: (x, y) 96 bytes or (flag | x) 48 bytes for compressed
     *   bls12-381-g2: (x_u * u + x, y_u * u + y) 192 bytes or (flag | x_u * u + x) 96 bytes for compressed
     * @param curve bls12-381, bls12-381-g2
     * @param data set of points each encoded as 96 bytes (or 48 bytes for compressed) bigendian integers 
     * @param compressed flag to represent compressed point
     * @return binary representation of point addition result
     * @throws IllegalArgumentException if the arguments are invalid
     */
    public static byte[] ecAdd(String curve, byte[] data, boolean compressed) {
        return null;
    }

    /**
     * Returns result of scalar multiplication as bigendian integers:
     *   bls12-381: (x, y) 96 bytes or (flag | x) 48 bytes for compressed
     *   bls12-381-g2: (x_u * u + x, y_u * u + y) 192 bytes or (flag | x_u * u + x) 96 bytes for compressed
     * @param curve bls12-381, bls12-381-g2
     * @param data set of points each encoded as 96 bytes (or 48 bytes for compressed) bigendian integers 
     * @param scalar 32 bytes scalar
     * @param compressed flag to represent compressed point
     * @return binary representation of scalar multiplication result
     * @throws IllegalArgumentException if the arguments are invalid
     */
    public static byte[] ecScalarMul(String curve, byte[] scalar, byte[] data, boolean compressed) {
        return null;
    }

    /**
     * Returns {@code true} if log_G1(a1) * log_G2(a2) + ... + log_G1(z1) + log_G2(z2) = 0
     * @param curve bls12-381
     * @param data set of alternating 
     *             G1 ((x, y) 96 bytes or (flag | x) 48 bytes for compressed bigendian integers) and 
     *             G2 points ((x_u * u + x, y_u * u + y) 192 bytes or (flag | x_u * u + x) 96 bytes for compressed bigendian integers) 
     * @param compressed flag to represent compressed points
     * @return boolean representing pairing check result
     * @throws IllegalArgumentException if the arguments are invalid
     */
    public static boolean ecPairingCheck(String curve, byte[] data, boolean compressed) {
        return false;
    }

Failed to build `cryptography`

When running a fresh build of v1.3.0 on Mac M1, the library cryptography fails to build.

This library is currently 2 years behind latest, see here

Current ver: v3.0.0
Latest ver: v38.0.3

Steps to reproduce:

  1. git clone https://github.com/icon-project/goloop
  2. brew install python rocksdb
  3. pip install virtualenv setuptools wheel
  4. cd goloop/
  5. virtualenv -p python3 venv
  6. . venv/bin/activate
  7. pip install -r pyee/requirements.txt

Stacktrace

#11 39.61   Building wheel for cryptography (pyproject.toml): started
#11 42.55   Building wheel for cryptography (pyproject.toml): finished with status 'error'
#11 42.57   error: subprocess-exited-with-error
#11 42.57   
#11 42.57   ร— Building wheel for cryptography (pyproject.toml) did not run successfully.
#11 42.57   โ”‚ exit code: 1
#11 42.57   โ•ฐโ”€> [341 lines of output]
#11 42.57       running bdist_wheel
#11 42.57       running build
...
#11 42.57       aarch64-linux-gnu-gcc -Wno-unused-result -Wsign-compare -DNDEBUG -g -fwrapv -O2 -Wall -g -fstack-protector-strong -Wformat -Werror=format-security -g -fwrapv -O2 -fPIC -I/usr/include/python3.10 -c build/temp.linux-aarch64-cpython-310/_openssl.c -o build/temp.linux-aarch64-cpython-310/build/temp.linux-aarch64-cpython-310/_openssl.o -Wconversion -Wno-error=sign-conversion
#11 42.57       build/temp.linux-aarch64-cpython-310/_openssl.c:2304:7: error: โ€˜EVP_PKEY_CTX_set_rsa_oaep_mdโ€™ redeclared as different kind of symbol
#11 42.57        2304 | int (*EVP_PKEY_CTX_set_rsa_oaep_md)(EVP_PKEY_CTX *, EVP_MD *) = NULL;
#11 42.57             |       ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
#11 42.57       In file included from /usr/include/openssl/x509.h:36,
#11 42.57                        from /usr/include/openssl/ct.h:29,
#11 42.57                        from build/temp.linux-aarch64-cpython-310/_openssl.c:639:
#11 42.57       /usr/include/openssl/rsa.h:158:5: note: previous declaration of โ€˜EVP_PKEY_CTX_set_rsa_oaep_mdโ€™ with type โ€˜int(EVP_PKEY_CTX *, const EVP_MD *)โ€™ {aka โ€˜int(struct evp_pkey_ctx_st *, const struct evp_md_st *)โ€™}
#11 42.57         158 | int EVP_PKEY_CTX_set_rsa_oaep_md(EVP_PKEY_CTX *ctx, const EVP_MD *md);
#11 42.57             |     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
#11 42.57       build/temp.linux-aarch64-cpython-310/_openssl.c:2311:7: error: โ€˜EVP_PKEY_CTX_set0_rsa_oaep_labelโ€™ redeclared as different kind of symbol
#11 42.57        2311 | int (*EVP_PKEY_CTX_set0_rsa_oaep_label)(EVP_PKEY_CTX *, unsigned char *,
#11 42.57             |       ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#11 42.57       In file included from /usr/include/openssl/x509.h:36,
#11 42.57                        from /usr/include/openssl/ct.h:29,
#11 42.57                        from build/temp.linux-aarch64-cpython-310/_openssl.c:639:
#11 42.57       /usr/include/openssl/rsa.h:164:5: note: previous declaration of โ€˜EVP_PKEY_CTX_set0_rsa_oaep_labelโ€™ with type โ€˜int(EVP_PKEY_CTX *, void *, int)โ€™ {aka โ€˜int(struct evp_pkey_ctx_st *, void *, int)โ€™}
#11 42.57         164 | int EVP_PKEY_CTX_set0_rsa_oaep_label(EVP_PKEY_CTX *ctx, void *label, int llen);
#11 42.57             |     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#11 42.57       build/temp.linux-aarch64-cpython-310/_openssl.c: In function โ€˜Cryptography_pem_password_cbโ€™:
#11 42.57       build/temp.linux-aarch64-cpython-310/_openssl.c:2955:37: warning: conversion to โ€˜size_tโ€™ {aka โ€˜long unsigned intโ€™} from โ€˜intโ€™ may change the sign of the result [-Wsign-conversion]
#11 42.57        2955 |         memcpy(buf, st->password, st->length);
#11 42.57             |                                   ~~^~~~~~~~
#11 42.57       build/temp.linux-aarch64-cpython-310/_openssl.c: In function โ€˜_cffi_const_CRYPTO_MEM_CHECK_DISABLEโ€™:
#11 42.57       build/temp.linux-aarch64-cpython-310/_openssl.c:6877:12: error: โ€˜CRYPTO_MEM_CHECK_DISABLEโ€™ undeclared (first use in this function); did you mean โ€˜_cffi_const_CRYPTO_MEM_CHECK_DISABLEโ€™?
#11 42.57        6877 |   int n = (CRYPTO_MEM_CHECK_DISABLE) <= 0;
#11 42.57             |            ^~~~~~~~~~~~~~~~~~~~~~~~
#11 42.57             |            _cffi_const_CRYPTO_MEM_CHECK_DISABLE
#11 42.57       build/temp.linux-aarch64-cpython-310/_openssl.c:6877:12: note: each undeclared identifier is reported only once for each function it appears in
#11 42.57       build/temp.linux-aarch64-cpython-310/_openssl.c: In function โ€˜_cffi_const_CRYPTO_MEM_CHECK_ENABLEโ€™:
#11 42.57       build/temp.linux-aarch64-cpython-310/_openssl.c:6884:12: error: โ€˜CRYPTO_MEM_CHECK_ENABLEโ€™ undeclared (first use in this function); did you mean โ€˜_cffi_const_CRYPTO_MEM_CHECK_ENABLEโ€™?
#11 42.57        6884 |   int n = (CRYPTO_MEM_CHECK_ENABLE) <= 0;
#11 42.57             |            ^~~~~~~~~~~~~~~~~~~~~~~
#11 42.57             |            _cffi_const_CRYPTO_MEM_CHECK_ENABLE
#11 42.57       build/temp.linux-aarch64-cpython-310/_openssl.c: In function โ€˜_cffi_const_CRYPTO_MEM_CHECK_OFFโ€™:
#11 42.57       build/temp.linux-aarch64-cpython-310/_openssl.c:6891:12: error: โ€˜CRYPTO_MEM_CHECK_OFFโ€™ undeclared (first use in this function)
#11 42.57        6891 |   int n = (CRYPTO_MEM_CHECK_OFF) <= 0;
#11 42.57             |            ^~~~~~~~~~~~~~~~~~~~
#11 42.57       build/temp.linux-aarch64-cpython-310/_openssl.c: In function โ€˜_cffi_const_CRYPTO_MEM_CHECK_ONโ€™:
#11 42.57       build/temp.linux-aarch64-cpython-310/_openssl.c:6898:12: error: โ€˜CRYPTO_MEM_CHECK_ONโ€™ undeclared (first use in this function)
#11 42.57        6898 |   int n = (CRYPTO_MEM_CHECK_ON) <= 0;
#11 42.57             |            ^~~~~~~~~~~~~~~~~~~
#11 42.57       build/temp.linux-aarch64-cpython-310/_openssl.c: In function โ€˜_cffi_const_EVP_R_KEYGEN_FAILUREโ€™:
#11 42.57       build/temp.linux-aarch64-cpython-310/_openssl.c:7615:12: error: โ€˜EVP_R_KEYGEN_FAILUREโ€™ undeclared (first use in this function)
#11 42.57        7615 |   int n = (EVP_R_KEYGEN_FAILURE) <= 0;
#11 42.57             |            ^~~~~~~~~~~~~~~~~~~~
#11 42.57       build/temp.linux-aarch64-cpython-310/_openssl.c: In function โ€˜_cffi_d_BIO_s_datagramโ€™:
#11 42.57       build/temp.linux-aarch64-cpython-310/_openssl.c:12006:10: warning: return discards โ€˜constโ€™ qualifier from pointer target type [-Wdiscarded-qualifiers]
#11 42.57       12006 |   return BIO_s_datagram();
#11 42.57             |          ^~~~~~~~~~~~~~~~
#11 42.57       build/temp.linux-aarch64-cpython-310/_openssl.c: In function โ€˜_cffi_f_BIO_s_datagramโ€™:
#11 42.57       build/temp.linux-aarch64-cpython-310/_openssl.c:12017:12: warning: assignment discards โ€˜constโ€™ qualifier from pointer target type [-Wdiscarded-qualifiers]
#11 42.57       12017 |   { result = BIO_s_datagram(); }
#11 42.57             |            ^
#11 42.57       build/temp.linux-aarch64-cpython-310/_openssl.c: In function โ€˜_cffi_d_BIO_s_memโ€™:
#11 42.57       build/temp.linux-aarch64-cpython-310/_openssl.c:12032:10: warning: return discards โ€˜constโ€™ qualifier from pointer target type [-Wdiscarded-qualifiers]
#11 42.57       12032 |   return BIO_s_mem();
#11 42.57             |          ^~~~~~~~~~~
#11 42.57       build/temp.linux-aarch64-cpython-310/_openssl.c: In function โ€˜_cffi_f_BIO_s_memโ€™:
#11 42.57       build/temp.linux-aarch64-cpython-310/_openssl.c:12043:12: warning: assignment discards โ€˜constโ€™ qualifier from pointer target type [-Wdiscarded-qualifiers]
#11 42.57       12043 |   { result = BIO_s_mem(); }
#11 42.57             |            ^
#11 42.57       build/temp.linux-aarch64-cpython-310/_openssl.c: In function โ€˜_cffi_d_CRYPTO_mem_ctrlโ€™:
#11 42.57       build/temp.linux-aarch64-cpython-310/_openssl.c:14916:10: warning: implicit declaration of function โ€˜CRYPTO_mem_ctrlโ€™; did you mean โ€˜CRYPTO_memcmpโ€™? [-Wimplicit-function-declaration]
#11 42.57       14916 |   return CRYPTO_mem_ctrl(x0);
#11 42.57             |          ^~~~~~~~~~~~~~~
...
#11 42.57       error: command '/usr/bin/aarch64-linux-gnu-gcc' failed with exit code 1
#11 42.57       [end of output]
#11 42.57   
#11 42.57   note: This error originates from a subprocess, and is likely not a problem with pip.
#11 42.57   ERROR: Failed building wheel for cryptography
#11 42.57 Successfully built msgpack coincurve
#11 42.57 Failed to build cryptography
#11 42.57 ERROR: Could not build wheels for cryptography, which is required to install pyproject.toml-based projects

I am able to install the latest version of this library so I assume it's just a simple version upgrade

RPC system error when calling get balanced on governance addresses

Don't know if this is something worth looking at or fixing as it is an edge case, but when calling:

{
    "jsonrpc": "2.0",
    "method": "icx_getBalance",
    "id": 1234,
    "params": {
         "address": "hx0000000000000000000000000000000000000000"
    }
}

Or on hx0000000000000000000000000000000000000001, I get the following error:

Response={"jsonrpc":"2.0","error":{"code":-31000,"message":"SystemError: E1002:InvalidAddressPrefix(valid=cx0000000000000000000000000000000000000000)"},"id":1234}

I built in an exception handler in my logic for these addresses but figured I'd raise this as an issue to take note.

How to pass array as parameter using goloop CLI ?

Hello,

I'm trying to call a readonly method from a contract using the goloop rpc call command.
The parameter of this method takes an array of BigInteger as a parameter.

How is it possible to call that method using goloop rpc call ?

If I set the param like that, it fails: --param _amounts=[1,2,3]

Error: jsonrpc: code: -30006, message: E0006:InvalidParameter(type=[]int,json="\"[1,2,3]\""), data: <nil>

The format of the --raw parameter is not explicit. I tried --raw '{"_amounts":[1,2,3]}' but it didn't work:

Error: jsonrpc: code: -30006, message: E0006:MissingParam(param=_amounts), data: <nil>

Goloop make fails at RocksDB

I have been following the build guide found here: https://github.com/icon-project/goloop/blob/master/doc/build.md

The following are my specs and current versions
Screen Shot 2022-04-26 at 9 49 07 PM

  • go 1.18.1
  • python 3.10.2
  • rocksdb 7.0.3

After installing the required packages and pip libraries, I get the following output when running make in the goloop directory.

~/goloop (master) ยป make                                                        
[#] go build ./cmd/gochain
go build -tags "rocksdb" -ldflags "-X 'main.version=v1.2.4-10-gcd14224f' -X 'main.build=darwin/arm64 tags(rocksdb)-2022-04-26-21:39:13'" -o /Users/shack/goloop/bin/gochain ./cmd/gochain
# github.com/icon-project/goloop/common/db
common/db/rocks_db.go:34:11: fatal error: 'rocksdb/c.h' file not found
 #include "rocksdb/c.h"
          ^~~~~~~~~~~~~
1 error generated.
make: *** [gochain] Error 2

Missing block notifications in ICON btp_extension's websocket endpoint: /block

We made the following observation (in screenshot) when using wss://ctz.solidwallet.io/api/v3/icon_dex/block websocket endpoint.

Some of the successive block notifications were not consecutive. This lead to missing blocks in the chain and the verification failed. We're using the btp_extension endpoints (/block) in relay.

Missing block notifications that have no subscribed events can be handled in the relay. We were concerned about whether the endpoint also misses block notifications for the blocks that include subscribed events. Looks like it does.

Following screenshot shows the missing block notifications from ICON. Please look at the heights.

image

Following screenshot shows the actual values when it doesn't miss anything. We reconnected the websocket to get the second one. So, one solution would be to simply reestablish the websocket connection and try again. I guess this is the simplest solution for now. But I hope we can look into it in goloop and fix the root cause.

image

NOTE: We cannot reproduce this with certainty, and have only observed this infrequently.

int implicitely converted to BigInteger in interscore call

For unknown reason, an int return type from a foreign SCORE is converted to BigInteger through an interscore call.

Repro code:

package com.iconloop.score.example;

import score.Address;
import score.Context;

public class HelloWorld {
    private final int decimals;

    public HelloWorld() {
        // cx2597d4374478674f94e69599301e5f31146bd71d is the address of a standard IRC2 Java contract
        Address target = Address.fromString("cx2597d4374478674f94e69599301e5f31146bd71d");
        this.decimals = (int) Context.call(target, "decimals");
    }
}

The relevant error during deployment (that error also happens after deployment by calling any method)

DApp deployment failed: java.lang.ClassCastException: class s.java.math.BigInteger cannot be cast to class 
s.java.lang.Integer (s.java.math.BigInteger and s.java.lang.Integer are in unnamed module of loader 'app')

The entire iconee.log when deploying to localnet:

callhandler.go:281 Execution INVOKE last=0 eid=1
proxy.go:235 Proxy[0xc0004d8c80].Invoke code=/testsuite/chain/iconee/contract/0xb0099b3a6ce34422125c32572671bd007272ebd23e445800ef4b3952f198b35d query=false from=hxb6b5791be0b5ef67063b3c10b840fb81514db2fd to=cx735e2a5e0088ef43ba8e4ee45fcf7b3b788422cf value=0 limit=1473895800 method=<init> eid=1
log.go:205  [INVOKE]
log.go:205  >>> code=/testsuite/chain/iconee/contract/0xb0099b3a6ce34422125c32572671bd007272ebd23e445800ef4b3952f198b35d
log.go:205      isQuery=false
log.go:205      from=hxb6b5791be0b5ef67063b3c10b840fb81514db2fd
log.go:205        to=cx735e2a5e0088ef43ba8e4ee45fcf7b3b788422cf
log.go:205      value=0
log.go:205      limit=1473895800
log.go:205      method=<init>
log.go:205      params=[
log.go:205      ]
log.go:205  >>> getInfo: info={B.height=294, B.timestamp=1631009433329336, C.owner=hxb6b5791be0b5ef67063b3c10b840fb81514db2fd, Revision=277517, StepCosts={apiCall=10000, contractCall=25000, contractCreate=1000000000, contractDestruct=-70000, contractSet=30000, contractUpdate=1600000000, default=100000, delete=-240, eventLog=100, input=200, replace=80, set=320}, T.from=hxb6b5791be0b5ef67063b3c10b840fb81514db2fd, T.hash=[B@25ef0adf, T.index=0, T.nonce=0, T.timestamp=1631009433325000}
log.go:205      txHash=33f68fb76b78a6b456e91d4deeebb027b87689f0177faecbf6397f8c83dc959a
log.go:205      txIndex=0
log.go:205      txFrom=hxb6b5791be0b5ef67063b3c10b840fb81514db2fd
log.go:205      txTimestamp=1631009433325000
log.go:205      txNonce=0
log.go:205      blockHeight=294
log.go:205      blockTimestamp=1631009433329336
log.go:205      contractOwner=hxb6b5791be0b5ef67063b3c10b840fb81514db2fd
log.go:205      stepCosts={apiCall=10000, contractCall=25000, contractCreate=1000000000, contractDestruct=-70000, contractSet=30000, contractUpdate=1600000000, default=100000, delete=-240, eventLog=100, input=200, replace=80, set=320}
log.go:205  === DAppCreator ===
log.go:205  [getCode]
log.go:205  [getBlockTimestamp] ret=1631009433329336
log.go:205  [setTransformedCode] len=1225
log.go:205  [call] target=cx2597d4374478674f94e69599301e5f31146bd71d value=0 limit=1473894603 dataType=call dataObj={method=decimals, params=[Ljava.lang.Object;@44e204e2} 
proxy.go:432 Proxy[0xc0004d8c80].OnCall from=cx735e2a5e0088ef43ba8e4ee45fcf7b3b788422cf to=cx2597d4374478674f94e69599301e5f31146bd71d value=0 limit=1473894603 type=call data=&{{1 0xc0020d0840}}
callhandler.go:281 Execution INVOKE last=0 eid=2
proxy.go:235 Proxy[0xc0004d8c80].Invoke code=/testsuite/chain/iconee/contract/0x4dfb32b69817cf7281718d9db817d220cabd6c03eb6b26a82f1ca954dd037e75 query=true from=cx735e2a5e0088ef43ba8e4ee45fcf7b3b788422cf to=cx2597d4374478674f94e69599301e5f31146bd71d value=0 limit=1473869603 method=decimals eid=2
log.go:205  [INVOKE]
log.go:205  >>> code=/testsuite/chain/iconee/contract/0x4dfb32b69817cf7281718d9db817d220cabd6c03eb6b26a82f1ca954dd037e75
log.go:205      isQuery=true
log.go:205      from=cx735e2a5e0088ef43ba8e4ee45fcf7b3b788422cf
log.go:205        to=cx2597d4374478674f94e69599301e5f31146bd71d
log.go:205      value=0
log.go:205      limit=1473869603
log.go:205      method=decimals
log.go:205      params=[
log.go:205      ]
log.go:205  >>> getInfo: info={B.height=294, B.timestamp=1631009433329336, C.owner=hxb6b5791be0b5ef67063b3c10b840fb81514db2fd, Revision=277517, StepCosts={apiCall=10000, contractCall=25000, contractCreate=1000000000, contractDestruct=-70000, contractSet=30000, contractUpdate=1600000000, default=100000, delete=-240, eventLog=100, input=200, replace=80, set=320}, T.from=hxb6b5791be0b5ef67063b3c10b840fb81514db2fd, T.hash=[B@6d16a8b1, T.index=0, T.nonce=0, T.timestamp=1631009433325000}
log.go:205      txHash=33f68fb76b78a6b456e91d4deeebb027b87689f0177faecbf6397f8c83dc959a
log.go:205      txIndex=0
log.go:205      txFrom=hxb6b5791be0b5ef67063b3c10b840fb81514db2fd
log.go:205      txTimestamp=1631009433325000
log.go:205      txNonce=0
log.go:205      blockHeight=294
log.go:205      blockTimestamp=1631009433329336
log.go:205      contractOwner=hxb6b5791be0b5ef67063b3c10b840fb81514db2fd
log.go:205      stepCosts={apiCall=10000, contractCall=25000, contractCreate=1000000000, contractDestruct=-70000, contractSet=30000, contractUpdate=1600000000, default=100000, delete=-240, eventLog=100, input=200, replace=80, set=320}
proxy.go:359 Proxy[0xc0004d8c80].OnResult status=Success steps=34
callhandler.go:398 Execution RESULT last=1 eid=3
proxy.go:300 Proxy[0xc0004d8c80].SendResult status=<nil> steps=25034 last=1 eid=3
log.go:205  [RESULT]
log.go:205  [call] result=Result{status=0, stepUsed=25034, ret=18, eid=3, prevEID=1}
log.go:205  DApp deployment failed: java.lang.ClassCastException: class s.java.math.BigInteger cannot be cast to class s.java.lang.Integer (s.java.math.BigInteger and s.java.lang.Integer are in unnamed module of loader 'app')
i.UncaughtException: java.lang.ClassCastException: class s.java.math.BigInteger cannot be cast to class s.java.lang.Integer (s.java.math.BigInteger and s.java.lang.Integer are in unnamed module of loader 'app')
	at org.aion.avm.core.persistence.LoadedDApp.handleUncaughtException(LoadedDApp.java:355)
	at org.aion.avm.core.persistence.LoadedDApp.initMainInstance(LoadedDApp.java:287)
	at org.aion.avm.core.DAppCreator.runClinitAndCreateMainInstance(DAppCreator.java:118)
	at org.aion.avm.core.DAppCreator.create(DAppCreator.java:70)
	at foundation.icon.ee.score.AvmExecutor.runCommon(AvmExecutor.java:99)
	at foundation.icon.ee.score.AvmExecutor.runExternal(AvmExecutor.java:74)
	at foundation.icon.ee.score.AvmExecutor.run(AvmExecutor.java:61)
	at foundation.icon.ee.score.TransactionExecutor.handleInvoke(TransactionExecutor.java:155)
	at foundation.icon.ee.ipc.EEProxy.handleInvoke(EEProxy.java:311)
	at foundation.icon.ee.ipc.EEProxy.doHandleMessages(EEProxy.java:123)
	at foundation.icon.ee.ipc.EEProxy.handleMessages(EEProxy.java:109)
	at foundation.icon.ee.score.TransactionExecutor.connectAndRunLoop(TransactionExecutor.java:104)
	at foundation.icon.ee.score.TransactionExecutor.connectAndRunLoop(TransactionExecutor.java:96)
	at foundation.icon.ee.ipc.ExecutorManager.lambda$runExecutor$0(ExecutorManager.java:73)
	at java.base/java.lang.Thread.run(Thread.java:834)
Caused by: java.lang.ClassCastException: class s.java.math.BigInteger cannot be cast to class s.java.lang.Integer (s.java.math.BigInteger and s.java.lang.Integer are in unnamed module of loader 'app')
	at u.A.<init>(Unknown Source)
	at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
	at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
	at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
	at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:490)
	at org.aion.avm.core.persistence.LoadedDApp.initMainInstance(LoadedDApp.java:284)
	... 13 more
log.go:205  Result{status=1, stepUsed=26831, ret=UnknownFailure, eid=0, prevEID=0}
proxy.go:359 Proxy[0xc0004d8c80].OnResult status=UnknownFailure steps=26831

The "decimals" method definition in the standard IRC2 contract is the following :

@External(readonly=true)
public int decimals() {
    return decimals;
}

Is that the intended behavior ?

Allow BigInteger up to 33 bytes in order to store UINT256_MAX ?

In the current goloop version, we can't deploy the following statement without raising an exception:

BigInteger MAX_UINT256 = new BigInteger("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 16);
Caused by: java.lang.ArithmeticException
       at s.java.math.BigInteger.isValidLength(BigInteger.java:399)
       at s.java.math.BigInteger.setUnderlying(BigInteger.java:362)
       at s.java.math.BigInteger.<init>(BigInteger.java:28)
       at s.java.math.BigInteger.<init>(BigInteger.java:32)
       at u.x.x.x.HelloWorld.<init>(Unknown Source)

Indeed, the underlying BigInteger bytearray is 33 bytes long as it stores the number sign.

private boolean isValidLength(int length) {
if (length > 32) {
// we're limiting the size of BigInteger to 32 bytes to have better control over the billing
throw new ArithmeticException("Out of the supported range");
}
return true;
}

That makes things complicated for 256 bits unsigned int arithmetic. That's something usual in other smart contract programming languages, so porting becomes problematic with that limitation.

Would it be possible to increase that limit ?

tcp: no such host

Followed the instructions in the tutorial and the server is giving this.
image

Calling a write method in immutable mode

Hello,

I'm looking for a way to call a write method without modifying the DB state.

Here's my use case : let's say I have the following get_result function:

@External(readonly = true)
public BigInteger get_result () {
    this._some_very_complex_function(); // this method writes to the SCORE DB and modifies this.result
    return this.result.get(); // returns the value after state change
}

_some_very_complex_function is an internal method that updates the SCORE DB state, including this.result VarDB.

The purpose of calling get_result is to be able to read the result value after a state change, without actually modifying it.

However, as get_result is a readonly method, calling it will end into a status=E0009:AccessingWritableFromReadOnly error.


EVM allows calling write methods in readonly without modifying the contract state.
I know goloop also have a debug estimate step API that do this too. However, I haven't found a way to return the result of the method called, but only the estimated steps.

Is there a way to achieve what I'm looking for ?


Alternatively, I can rewrite _some_very_complex_function in order to avoid writing to the SCORE DB and write in temporary local variables instead. However, _some_very_complex_function is really big and complex, duplicating it would take a lot of contracts bytes (which is pretty limited), and wouldn't be great for maintainbility.

Getting odd status code some calls

We are getting some odd responses that we have never seen before on sejong.

StatusCode=400,
Request={
"jsonrpc": "2.0",
"id": 1234,
"method": "icx_call",
"params": {
    "to": "cxf5f3c028cedc26ec4740edecb926e6eee52b697f",
    "dataType": "call",
    "data": {
        "method": "decimals",
        "params": {}
    }
}
},
Response={"jsonrpc":"2.0","error":{"code":-30001,
"message":"SystemError(-30001): E0001:ProxyIsClosed"},"id":1234}

Contract exists. Call works fine against solidwallet / geometry endpoints but failing against a bare metal node that has batch set to 1000.

Expose `up=1` metric

There are a lot of great metrics but one that is common for prometheus is a simple up metric which equals one. With this we can write a simpler promql query to know if a node is active, ie up != 1 on a metric that we know should not change. This isn't as far as convention to have this metric but it is pretty standard.

We can PR this if you agreed on.

panic: division by zero error

Good day team!

Im running a local multi node chain, after cloning the goloop locally im building the image with the make gochain-icon-image (the image being build is v1.4.0-rc.1)

after that I run the multi node docker setup with docker compose, the nodes run succesfully but after a couple minutes they simply crash.

the logs of the nodes have the following info at the end

I|20240123-05:06:32.505286|e9df|8cb6dd|SV|iiss4.go:38 Global Option: GlobalV3{revision=25 iissVersion=4 startHeight=1 offsetLimit=299 electedPRepCount=0 bondRequirement=0 rFund=RewardFund{version=0 Iglobal=15552000000 Icps=0 Iprep=5000 Irelay=0 Ivoter=5000} minBond=0}
D|20240123-05:06:32.505346|e9df|8cb6dd|SV|iiss4.go:131 get event at 245 EventEnable{target=hxb6b5791be0b5ef67063b3c10b840fb81514db2fd status=Enable}
D|20240123-05:06:32.505365|e9df|8cb6dd|SV|prep.go:280 SetStatus: hxb6b5791be0b5ef67063b3c10b840fb81514db2fd to 0
D|20240123-05:06:32.505393|e9df|8cb6dd|SV|prep.go:350 CalculateReward()
D|20240123-05:06:32.505409|e9df|8cb6dd|SV|prep.go:353 RewardFund: PRep: 1800000000, wage: 0
panic: division by zero

goroutine 2529 [running]:
math/big.nat.div({0x0?, 0xb05f4f?, 0xc0005002a0?}, {0x0?, 0xc000ba1920?, 0x25?}, {0x0?, 0x913c6a?, 0xc002df2640?}, {0x0, ...})
        /usr/local/go/src/math/big/natdiv.go:520 +0x34b
math/big.(*Int).QuoRem(0xc002df2640, 0xc002df25e0, 0xc000b13dd8, 0xc000b13d18)
        /usr/local/go/src/math/big/int.go:286 +0x9c
math/big.(*Int).Div(0xd449df?, 0x16bbee7?, 0xc002df25a0?)
        /usr/local/go/src/math/big/int.go:297 +0x45
github.com/icon-project/goloop/icon/iiss/calculator.(*PRepInfo).CalculateReward(0xc002776140, 0x169c922?, 0x18dcbf0?, 0x18dcbf0?)
        /work/icon/iiss/calculator/prep.go:354 +0x1d6
github.com/icon-project/goloop/icon/iiss/calculator.(*iiss4Reward).processPrepReward(0xc0068ce750)
        /work/icon/iiss/calculator/iiss4.go:166 +0xae
github.com/icon-project/goloop/icon/iiss/calculator.(*iiss4Reward).Calculate(0xc0068ce750)
        /work/icon/iiss/calculator/iiss4.go:53 +0x1a6
github.com/icon-project/goloop/icon/iiss/calculator.(*calculator).run(0xc005142510)
        /work/icon/iiss/calculator/calculator.go:184 +0x1ab
created by github.com/icon-project/goloop/icon/iiss/calculator.New
        /work/icon/iiss/calculator/calculator.go:332 +0x24d

Im guessing that this might be because I havent registered any preps at this point so there is no prep to give rewards after a term so im going to try running the containers and then quickly registering preps

Dependeny warning yaml

I get a dependency warning when importing gopkg.in/yaml.v2 v2.2.1 and v2.2.2 (lines 220 - 222) via the go.sum file.

It throws this warning:

โ€œThe Kubernetes API Server component in versions 1.1-1.14, and versions prior to 1.15.10, 1.16.7 and 1.17.3 allows an authorized user who sends malicious YAML payloads to cause the kube-apiserver to consume excessive CPU cycles while parsing YAML.โ€

I fixed it by setting the versions to v2.2.8. Should be something to look at, perhaps.

Issue creating public key per the update for BTP

I ran into this issue trying to generate the public key per these docs - https://docs.icon.community/getting-started/how-to-run-a-validator-node/register-prep-node-public-key#register-public-key

2023/09/16 21:31:14 Fail to decrypt KeyStore err=invalid character 'รฏ' looking for beginning of value
panic: Fail to decrypt KeyStore err=invalid character 'รฏ' looking for beginning of value

goroutine 1 [running]:
log.Panicf({0x168cf1f?, 0x7ffc1a07ab40?}, {0xc00063fcc8?, 0xc000593de0?, 0x0?})
        /home/linuxbrew/.linuxbrew/Cellar/go/1.19.5/libexec/src/log/log.go:395 +0x67
github.com/icon-project/goloop/cmd/cli.publickeyFromKeyStore.func1(0xc000100000?, {0x1668908?, 0x4?, 0x4?})
        /home/rob/code/icon-project/goloop/cmd/cli/keystore.go:149 +0x1f9
github.com/spf13/cobra.(*Command).execute(0xc000100000, {0xc0005a2d40, 0x4, 0x4})
        /home/rob/go/pkg/mod/github.com/spf13/[email protected]/command.go:920 +0x847
github.com/spf13/cobra.(*Command).ExecuteC(0xc0003ea000)
        /home/rob/go/pkg/mod/github.com/spf13/[email protected]/command.go:1044 +0x3bd
github.com/spf13/cobra.(*Command).Execute(...)
        /home/rob/go/pkg/mod/github.com/spf13/[email protected]/command.go:968
main.main()
        /home/rob/code/icon-project/goloop/cmd/goloop/main.go:58 +0x278

Issue is related to this SO post - not really sure what is going on there.

Regardless I am submitting this PR which fixed it for me running linux.

AccessDenied when setting static variables in helper classes.

The situation where this error is seen is when using "static" helper classes in Java score.
The intended behavior of static variables in Java score according to my understanding is that they should be saved and only reset during upgrades.
But when using static variables from helper classes i noticed they seem to behave as instance variables (reset for each call). Since there is a limit to instance variables, my guess is that this bug arises when writing to a variable above this limit and causing a stack overflow.

Not entirely sure what is going on but seems that something is unclear here.
TX hash where this occurs: https://tracker.lisbon.icon.community/transaction/trace/0x29f4500147f4179bfb6190140da2e3cbf36a675a6be37b28c823d38aebbe4094

Discussion on the native support for BN254 curve

After the successful completion of addition of BLS12-381 curve, we want to start a discussion on addition of BN254 curve. We've already submitted a CPS proposal, and started a community forum discussion. While the forum post is open for comment, it makes sense to start a discussion here to reach a bigger audience and more stakeholders so that meaningful development of Zero-Knowledge powered applications on ICON is not postponed.

Implementation
We have utilized the code from the BN128 codebase of the EthereumJ client and have achieved a basic integration. Note that this is just for PoC and is not the final form.

In the final form, we intend to incorporate comprehensive trusted tests for curve operations sourced from Google and Cloudflare to ensure the code's quality and reliability. These tests have helped maintain the security of curve operations on Ethereum and thus will help validate the correctness and performance of the curve operations, ensuring that the integration meets the desired standards.

Unless a bug is found on Ethereum's implementation, once released, our implementation would not require any changes. Given how long the code has been running on Ethereum, the chances of the bug is pretty unlikely.

Benefits of the BN254 Curve: Community Base, Tooling Support, and Circuit Compatibility
BN254 curve boasts a vast community base and robust tooling support, making it an attractive choice for numerous projects. The widely used circomlib library, for instance, retains all its circuits and Javascript client library compatible with the BN254 curve. Notably, this library capitalizes on the baby jubjub curve, which possesses a unique property: its base field aligns with the scalar field of the BN254. This alignment enables the native SNARK computation to be leveraged for an efficient implementation. Consequently, various crucial functionalities, such as the implementation of Pedersen hash/commitments, Poseidon hash/shared_key_encryption, EdDSA signature verification on a snark circuit, and other use cases, have been made possible.

Accelerating Privacy-Preserving Protocols and Applications in the ICON Network: Leveraging the BN254 Curve
The constructs discussed above serve as the foundation for major privacy-preserving protocols (like Semaphore) and applications (like Railgun). With BN254, bringing these into the ICON network would only require minimal changes to the frontend and smart contracts, as the circuits and utility libraries can be reused. Without the BN254 curve, however, developers would need to implement some of these circuits from scratch, which presents significant challenges. Writing circuits requires an in-depth understanding of mathematics and cryptography, making it an expensive, complex, and time-consuming task. Moreover, starting from scratch introduces a higher risk of potential bugs.

BN254 Curve Adoption: Security and Reliability in Practice
BLS12-381 indeed provides a better security of 120 bits over 100 bits for BN254. However, the BN254 curve is secure enough that many-large scale projects still rely on it. These include:

  • Polygon zkEVM: The alt_bn128 curve is employed within the Polygon zkEVM implementation.
  • zkSync: The BN254 or altBN128 curve is used for the final commitment verifier in zksync/VerifierTemplate.sol.
  • Loopring: The bn128 curve is employed in protocols/Verifier.sol within the Loopring project.
  • Scroll zkEVM: The bn254 curve is utilized in the PLONK verifier within the scroll-zkevm repository.

Conclusion
While it is anticipated that these projects will eventually transition to the BLS12-381 curve as tooling support improves, the current landscape suggests that this migration process will require a substantial amount of time. By incorporating the BN254 curve into the ICON network, we aim to facilitate a seamless development experience for dApp developers and enable them to build new applications or repurpose existing ones, while leveraging the available resources. It is worth noting that working with Zero Knowledge protocols can be challenging, even for experienced developers. Therefore, it is imperative that we prioritize simplifying the initial steps for developers to embark on their Zero Knowledge journey. Should individuals desire enhanced security, they can always opt to switch to utilizing the BLS12-381 curve.

Error when building goloop-0.9.4

Hello,

I got this error when following the build instructions on a Linux & Mac environment :

$ wget https://github.com/icon-project/goloop/archive/v0.9.4.zip && unzip v0.9.4.zip && cd goloop-0.9.4
$ python3 -m venv ./venv
$ source ./venv/bin/activate
$ pip3 install -r pyee/requirements.txt
$ make

It outputs the following error

go build ./cmd/goloopgo build -tags "" -ldflags "-X 'main.version=v0.9.4' -X 'main.build=linux/amd64 tags()-2021-02-02-16:41:28'" -o ./bin/goloop ./cmd/goloop
# github.com/icon-project/goloop/icon/iiss
icon/iiss/base.go:212:2: cannot use tx (type *baseV3) as type transaction.Transaction in return argument:
    *baseV3 does not implement transaction.Transaction (missing IsSkippable method)
icon/iiss/base.go:233:2: cannot use tx (type *baseV3) as type transaction.Transaction in return argument:
    *baseV3 does not implement transaction.Transaction (missing IsSkippable method)

Is there's something missing in the build instructions or am I missing something ?

Thanks!

`getPreps` in System Score in gochain-local doesn't take parameters

According to api specification getPreps method takes start ranking and end ranking parameters.
https://github.com/icon-project/goloop/blob/master/doc/iiss_extension.md#getpreps. Although, in gochain-local supplying parameters for getPreps method gives illegal argument exception.

T|20220322-09:19:12.621368|b6b5|3325fd|SV|2d6aed0b|log.go:205 java|cxbb63b132|foundation.icon.ee.score.ExternalState [call] target=cx0000000000000000000000000000000000000000 value=0 limit=783739547 dataType=call dataObj={params=[Ljava.lang.Object;@6c1ed24a, method=getPReps} 
T|20220322-09:19:12.621532|b6b5|3325fd|SV|2d6aed0b|proxy.go:466 Proxy[0xc0004c5f00].OnCall from=cxbb63b132573d9fb2226ce5158bbaf174b964e46c to=cx0000000000000000000000000000000000000000 value=0 limit=783739547 type=call data=&{{1 0xc0019dc240}}
T|20220322-09:19:12.622900|b6b5|3325fd|SV|callhandler.go:394 Execution RESULT last=2 eid=3
T|20220322-09:19:12.623032|b6b5|3325fd|SV|2d6aed0b|proxy.go:334 Proxy[0xc0004c5f00].SendResult status=E0006:Failed to get PReps: start=1 end=100 steps=25000 last=2 eid=3
T|20220322-09:19:12.623679|b6b5|3325fd|SV|2d6aed0b|log.go:205 java|cxbb63b132|foundation.icon.ee.ipc.EEProxy [RESULT]
T|20220322-09:19:12.623782|b6b5|3325fd|SV|2d6aed0b|log.go:205 java|cxbb63b132|foundation.icon.ee.score.ExternalState [call] result=Result{status=6, stepUsed=25000, ret=Failed to get PReps: start=1 end=100, eid=3, prevEID=2}
T|20220322-09:19:12.624509|b6b5|3325fd|SV|2d6aed0b|log.go:205 java|cxbb63b132|org.aion.avm.core.DAppCreator DApp deployment failed: java.lang.IllegalArgumentException: InvalidParameter
D|20220322-09:19:12.625495|b6b5|-|javaee|i.UncaughtException: java.lang.IllegalArgumentException: InvalidParameter
D|20220322-09:19:12.626568|b6b5|-|javaee|	at org.aion.avm.core.persistence.LoadedDApp.handleUncaughtException(LoadedDApp.java:360)
D|20220322-09:19:12.626619|b6b5|-|javaee|	at org.aion.avm.core.persistence.LoadedDApp.initMainInstance(LoadedDApp.java:290)
D|20220322-09:19:12.626649|b6b5|-|javaee|	at org.aion.avm.core.DAppCreator.runClinitAndCreateMainInstance(DAppCreator.java:124)
D|20220322-09:19:12.626700|b6b5|-|javaee|	at org.aion.avm.core.DAppCreator.create(DAppCreator.java:73)
D|20220322-09:19:12.627043|b6b5|-|javaee|	at foundation.icon.ee.score.AvmExecutor.runCommon(AvmExecutor.java:99)
D|20220322-09:19:12.627086|b6b5|-|javaee|	at foundation.icon.ee.score.AvmExecutor.runExternal(AvmExecutor.java:74)
D|20220322-09:19:12.627115|b6b5|-|javaee|	at foundation.icon.ee.score.AvmExecutor.run(AvmExecutor.java:61)
D|20220322-09:19:12.627373|b6b5|-|javaee|	at foundation.icon.ee.score.TransactionExecutor.handleInvoke(TransactionExecutor.java:145)

If no parameters are provided the call works.

T|20220322-08:59:22.730005|b6b5|3325fd|SV|2d6aed0b|log.go:205 java|cx1a880a2b|foundation.icon.ee.score.ExternalState [call] target=cx0000000000000000000000000000000000000000 value=0 limit=784047639 dataType=call dataObj={params=[Ljava.lang.Object;@3eb6e668, method=getPReps} 
T|20220322-08:59:22.730104|b6b5|3325fd|SV|2d6aed0b|proxy.go:466 Proxy[0xc0004c5f00].OnCall from=cx1a880a2b89dbd8851275db74000f4f57ce272ec9 to=cx0000000000000000000000000000000000000000 value=0 limit=784047639 type=call data=&{{1 0xc00007f8c0}}
T|20220322-08:59:22.731273|b6b5|3325fd|SV|callhandler.go:394 Execution RESULT last=2 eid=3
T|20220322-08:59:22.731308|b6b5|3325fd|SV|2d6aed0b|proxy.go:334 Proxy[0xc0004c5f00].SendResult status=<nil> steps=25000 last=2 eid=3
T|20220322-08:59:22.731646|b6b5|3325fd|SV|2d6aed0b|log.go:205 java|cx1a880a2b|foundation.icon.ee.ipc.EEProxy [RESULT]
T|20220322-08:59:22.731960|b6b5|3325fd|SV|2d6aed0b|log.go:205 java|cx1a880a2b|foundation.icon.ee.score.ExternalState [call] result=Result{status=0, stepUsed=25000, ret={blockHeight=125, preps=[Ljava.lang.Object;@15dbc64a, startRanking=1, totalDelegated=0, totalStake=0}, eid=3, prevEID=2}

There is difference in behavior in working of getPreps method than the specification.

Inconsistency between endpoints

When querying sejong API, I am not able to query contract method on my own nodes vs solidwallet nodes.

import requests
import json

url = "http://108.61.103.8:9010/api/v3"
payload = {
    "jsonrpc": "2.0",
    "id": 1,
    "method": "icx_call",
    "params": {
        "to": "cx79a1d066c9bab28090d9fc621a8212ca681a3553",
        "dataType": "call",
        "data": {"method": "name"},
    },
}

r = requests.post(url=url, data=json.dumps(payload)).json()
assert r['error']['message'] == 'SystemError(-30001): E0001:ProxyIsClosed'

url = "https://sejong.net.solidwallet.io/api/v3"
r = requests.post(url=url, data=json.dumps(payload)).json()
assert r['result'] == 'Snapshot'

Reported this before #99 but wanted to give a concrete example. Nothing is showing in the logs on the node side. It is able to respond to other requests such as icx_getScoreApi on this contract and others but failing on this call for this contract and about 25% of all the other contracts on Sejong.

Websocket inconsistencies

Hello again! I'm trying to make sense of ICON 2.0 websockets' notifications and I'm having a hard time figuring them out. So far I have a working prototype where I can connect to the websocket and start receiving the notifications:

  • I'm testing with wss://ctz.solidwallet.io/api/v3/icon_dex/event (Mainnet).
  • I followed the documentation found here
  • I'm trying to subscribe to the Swap event from Balanced DEx:
    • Address: cxa0af3165c08318e988cb30993b3048335b94af6c
    • Signature: Swap(int,Address,Address,Address,Address,Address,int,int,int,int,int,int,int,int,int)
    • Match any indexed fields: [null, null]
    • Match any data fields: [null, null, null, null, null, null, null, null, null, null, null, null, null]

Note: I usually request the latest block height and use that height as starting height in the payload.

So, after establishing a connection with the websocket, I send the following text frame to the websocket (formatted for readability):

{
  "height": "0x2cb7f81",
  "event": "Swap(int,Address,Address,Address,Address,Address,int,int,int,int,int,int,int,int,int)",
  "addr": "cxa0af3165c08318e988cb30993b3048335b94af6c",
  "indexed": [null, null],
  "data": [null, null, null, null, null, null, null, null, null, null, null, null, null]
}

So, the first notification I got was this one:

{
  "events": ["0x4"],
  "hash": "0xa82d7793a972bd46550503ff23039f05e04da8df90d69735dfd2f96ab982b84b",
  "height": "0x2cb7f88",
  "index": "0x1"
}

So, what I understand about the notification:

  • height is the height of the block: 46890888
  • hash is the hash of the block: It matches the one shown in the previous link.
  • index is the index of the transaction in confirmed_transaction_list which triggered the event. If we start counting from 0, then it would be the second transaction in the block, which is 0xdd22de95b534b0be5b174aada9bb103d0fbc2bb5e0f02b85381b681c6f53ff28
  • events is a list of logs indexes where we can find the event that matched our initial query. So, the event I'm interested in would be the 5th log entry, but the event does not match the one I'm expecting:
    {
      "scoreAddress":"cxb0b6f777fba13d62961ad8ce11be7ef6c4b2bcc6",
      "indexed": [
        "BetPlaced(int,int,int)",
        "0x4563918244f40000",
        "0x58",
        "0x0"
      ],
      "data":[]
    }

So, the result doesn't seem consistent with my first request. Is the payload incorrect? Or did I stumble upon a bug?

This is the PR I'm working on at the moment in my Elixir ICON 2.0 SDK if you're curious of what I'm trying to accomplish.

Node is stuck in `candidate` status while in main after migration

Recently I migrated my node on mainnet which was synced up as a citizen and then converted to a prep and it is now stuck as being a candidate and accruing penalties. Node was migrated over 1 term ago and should have come back into rotation.

To migrate the node I ran:

preptools setPRep --config preptools_config.json --node-address hx7f035c0fc573cb6c1ff17cd2b6678f0a17f491f3 --prep-json registerPRep.json

Which resulted in this Tx hash: https://tracker.icon.community/transaction/0x6dc6980b8aee3d9817b2b2eaed743ba149f8b92cd30a21df37ef1ca5570c1a5c

And then verifying via getPrep RPC that the data is in fact on chain, scraping the /metrics endpoint and validating a few metrics indicative of a healthy node.

import requests
import json

url = "https://api.icon.community/api/v3"
payload = {
    "jsonrpc": "2.0",
    "id": 1,
    "method": "icx_call",
    "params": {
        "to": "cx0000000000000000000000000000000000000000",
        "dataType": "call",
        "data": {
            "method": "getPRep",
            "params": {
                "address": "hxfc56203484921c3b7a4dee9579d8614d8c8daaf5"
            }
        }
    },
}

r = requests.post(url=url, data=json.dumps(payload)).json()

assert r['result']['grade'] == '0x2'  # This shows the node is in "candidate" state  

p2p_endpoint = r['result']['p2pEndpoint']
assert p2p_endpoint == '139.180.184.203:7100'
metrics_endpoint = 'http://' + p2p_endpoint.split(':')[0] + ':9000/metrics'
assert metrics_endpoint == 'http://139.180.184.203:9000/metrics'

r = requests.get(url=metrics_endpoint)
for i in r.text.split('\n'):
    if i.startswith('goloop_consensus_height_duration'):
        goloop_consensus_height_duration = int(i.split()[-1])
        # These are good ranges for this metric showing healthy node
        assert goloop_consensus_height_duration > 1500
        assert goloop_consensus_height_duration < 2500
    elif i.startswith('goloop_consensus_height'):
        goloop_consensus_height = int(float(i.split()[-1]))
        # Show that it is at a recent block (it is synced...)
        assert goloop_consensus_height > 50460693

Nothing in the logs is telling me that anything is wrong. Node has been restarted several times to make sure new config was brought in.

  mainnet:                                                                                                                                                                                                         
    image: 'iconloop/icon2-node'                                                                                                                                                                                   
    restart: "on-failure"                                                                                                                                                                                          
    stdin_open: true                                                                                                                                                                                               
    cap_add:                                                                                                                                                                                                       
      - SYS_TIME                                                                                                                                                                                                   
    volumes:                                                                                                                                                                                                       
      - ./mainnet/data:/goloop/data                                                                                                                                                                                
      - ./mainnet/logs:/goloop/logs                                                                                                                                                                                
      - ./mainnet/config:/goloop/config                                                                                                                                                                            
    environment:                                                                                                                                                                                                   
      SERVICE: MainNet                                                                                                                                                                                             
      GOLOOP_LOG_LEVEL: "debug"                                                                                                                                                                                    
      FASTEST_START: "true"                                                                                                                                                                                        
      ROLE: 3                                                                                                                                                                                                      
      IS_AUTOGEN_CERT: "true"                                                                                                                                                                                      
      GOLOOP_P2P_LISTEN: ":7100"
      GOLOOP_RPC_ADDR: ":9000"
      KEY_PASSWORD: "nunyabiznis"
      KEY_STORE_FILENAME: keystore
    ports:
      - 7100:7100
      - 9000:9000

Which successfully loads the keystore and is the right address:

Successfully loaded Keystore file(json), address=hx40f9e6a0b54b8dd9d90732aaee4f9789550092c7, file=/goloop/config/keystore

Last tidbit that might be useful is that it didn't seem like this node was peered properly with the network but I am still looking into that.

Berlin network crash

I just had all of my berlin nodes crash. I understand that this was because of the reset but I am not sure how to recover properly. I restarted nodes and they aren't producing new blocks. I wiped a DB and it came back tot he same BH even though the foundation tracker is showing a BH in the 144,428 range.

Do I need to set a new mig endpoint or something to recover properly? Also to be clear, all the contracts are lost and need to be redeployed correct? So I should also wipe all my indexes as well?

This was the last log but I don't think it matters considering the above....

berlin_1         |  7 Nov 02:51:56 ntpdate[2116]: adjust time server 17.253.52.253 offset -0.000021 sec
berlin_1         |  7 Nov 05:52:03 ntpdate[2121]: adjust time server 17.253.52.253 offset +0.000026 sec
berlin_1         | Task exception was never retrieved
berlin_1         | future: <Task finished coro=<NodeChecker.check_node() done, defined at /ctx/manager/node_checker.py:62> exception=SystemExit(127)>
berlin_1         | Traceback (most recent call last):
berlin_1         |   File "/usr/local/lib/python3.7/asyncio/runners.py", line 43, in run
berlin_1         |     return loop.run_until_complete(main)
berlin_1         |   File "/usr/local/lib/python3.7/asyncio/base_events.py", line 574, in run_until_complete
berlin_1         |     self.run_forever()
berlin_1         |   File "/usr/local/lib/python3.7/asyncio/base_events.py", line 541, in run_forever
berlin_1         |     self._run_once()
berlin_1         |   File "/usr/local/lib/python3.7/asyncio/base_events.py", line 1786, in _run_once
berlin_1         |     handle._run()
berlin_1         |   File "/usr/local/lib/python3.7/asyncio/events.py", line 88, in _run
berlin_1         |     self._context.run(self._callback, *self._args)
berlin_1         |   File "/ctx/manager/node_checker.py", line 134, in check_node
berlin_1         |     sys.exit(127)
berlin_1         | SystemExit: 127
task ${TASK_NAME} exiting with exit code 127
berlin_1         | task ${TASK_NAME} exiting with exit code 256
berlin_1         | [cont-finish.d] executing container finish scripts...
berlin_1         | [cont-finish.d] graceful_shutdown: executing... 
berlin_1         | s6-svscanctl: fatal: unable to control /var/run/s6/services: supervisor not listening
berlin_1         | [cont-finish.d] graceful_shutdown: exited 100.
berlin_1         | [cont-finish.d] done.
berlin_1         | [s6-finish] waiting for services.
berlin_1         | [s6-finish] sending all processes the TERM signal.
berlin_1         | [s6-finish] sending all processes the KILL signal and exiting.

We had this error on Mainnet

|20221211-01:58:16.911052|54d6|1|BM|manager.go:826 ImportBlock(626c1765771dba0f0183911e447443427c55d3745fd63f017e1ed9c66a2f9200)
P|20221211-01:58:16.911085|54d6|1|CS|consensus.go:935 commitAndEnterNewHeight: InvalidPreviousID(cbbdcab71a483b4ca75ba1c56e219d6ce7702ac95af7135c49e17dd43397c1b6)
github.com/icon-project/goloop/block.(*manager)._import
/work/block/manager.go:310
github.com/icon-project/goloop/block.(*manager).ImportBlock
/work/block/manager.go:828
github.com/icon-project/goloop/consensus.(*consensus).commitAndEnterNewHeight
/work/consensus/consensus.go:909
github.com/icon-project/goloop/consensus.(*consensus).enterCommit
/work/consensus/consensus.go:973
github.com/icon-project/goloop/consensus.(*consensus).processBlock
/work/consensus/consensus.go:2074
github.com/icon-project/goloop/consensus.(*consensus).ReceiveBlock
/work/consensus/consensus.go:2025
github.com/icon-project/goloop/consensus.(*syncer).OnBlock
/work/consensus/syncer.go:509
runtime.goexit
/usr/local/go/src/runtime/asm_amd64.s:1571
panic: (*logrus.Entry) 0xc006be3d50

goroutine 7384577 [running]:
[github.com/sirupsen/logrus.Entry.log({0xc0000e6070](http://github.com/sirupsen/logrus.Entry.log(%7B0xc0000e6070), 0xc00071cf90, {0x0, 0x0, 0x0}, 0x0, 0x0, {0x0, 0x0}, 0x0, ...}, ...)
/go/pkg/mod/github.com/sirupsen/[email protected]/entry.go:259 +0x2de
[github.com/sirupsen/logrus.(*Entry).Log(0xc000372b60](http://github.com/sirupsen/logrus.(*Entry).Log(0xc000372b60), 0x0, {0xc02a93dc70?, 0x1?, 0x1?})
/go/pkg/mod/github.com/sirupsen/[email protected]/entry.go:287 +0xa8
[github.com/sirupsen/logrus.(*Entry).Logf(0xc000372b60](http://github.com/sirupsen/logrus.(*Entry).Logf(0xc000372b60), 0x0, {0x149244a?, 0x86e0c7?}, {0xc0510b8780?, 0x12db7e0?, 0xc02a93dc01?})
/go/pkg/mod/github.com/sirupsen/[email protected]/entry.go:333 +0x85
[github.com/sirupsen/logrus.(*Entry).Panicf(0xc0001aea90](http://github.com/sirupsen/logrus.(*Entry).Panicf(0xc0001aea90)?, {0x149244a?, 0xc041bc3e60?}, {0xc0510b8780?, 0x0?, 0xc00023cb10?})
/go/pkg/mod/github.com/sirupsen/[email protected]/entry.go:371 +0x34
github.com/icon-project/goloop/consensus.(*consensus).commitAndEnterNewHeight(0xc000192840)
/work/consensus/consensus.go:935 +0x1c6
[github.com/icon-project/goloop/consensus.(*consensus).enterCommit(0xc000192840](http://github.com/icon-project/goloop/consensus.(*consensus).enterCommit(0xc000192840), 0x15fe728?, 0xc0015527c0, 0x0)
/work/consensus/consensus.go:973 +0x3c6
[github.com/icon-project/goloop/consensus.(*consensus).processBlock(0xc000192840](http://github.com/icon-project/goloop/consensus.(*consensus).processBlock(0xc000192840), {0x15fb6d8, 0xc0419fd810})
/work/consensus/consensus.go:2074 +0x69e
[github.com/icon-project/goloop/consensus.(*consensus).ReceiveBlock(0xc000192840](http://github.com/icon-project/goloop/consensus.(*consensus).ReceiveBlock(0xc000192840), {0x15fb6d8, 0xc0419fd810})
/work/consensus/consensus.go:2025 +0x205
[github.com/icon-project/goloop/consensus.(*syncer).OnBlock(0xc00023ca80](http://github.com/icon-project/goloop/consensus.(*syncer).OnBlock(0xc00023ca80), {0x15fb6d8, 0xc0419fd810})
/work/consensus/syncer.go:509 +0x150
created by github.com/icon-project/goloop/consensus/fastsync.(*client).notifyBlockResult
/work/consensus/fastsync/client.go:354 +0xef

Recommendations for how to increase goloop RPC performance

I am loading up goloop with RPC calls and am seeing major performance degradation as the number of requests goes up to the point that goloop slows down to being only able to serve ~10 requests per second. This has nothing to do with the CPU / system resources / network as we are testing goloop on a single large dedicated node with 48 threads and watching the CPU, it goes down to near 0 when the stalls happen.

We have tried changing the batch limit and modifying the amount of requests we are sending it at a time. While we are able to send 10s of thousands of RPS, goloop seems to initially be able to serve >1k RPS but over the course of a couple minutes the RPS will slow down to ~10.

Question would be is there anything that can be set to increase performance? I am looking through the goloop code and I see references to a cpu profile, max_rps, max_workers, and concurrency but am not able to decipher 1, how to even set these parameters and 2, which ones I could modify to see if they have an impact on performance.

While I am not still trying to diagnose this, this definitely seems like a bug with goloop because CPU should not drop to 0 when performance drops to 0.

As more context, this is for supporting a new version of the tracker backend / indexer along with how to properly deploy the community API nodes. We have access to large bare metal nodes but given that CPU doesn't seem to be that important, we might be better off load balancing across a larger set smaller nodes than a few very powerful ones. This is going to be far less efficient though than being able to actually use the resources of a large node. This is a very important item for us to flush out as it has direct impact on the performance of our stack.

getPReps RPC returning wrong data

Running getPReps (RPC below) returns what I believe is old data from ICON 1.0 as the p2pEndpoint is not right for a lot of nodes. For instance for ICON Asset Management, the right IP is 54.68.57.186 which calling the below RPC returns "p2pEndpoint": "44.235.212.252:7100".

{
  "jsonrpc": "2.0",
  "id": 1234,
  "method": "icx_call",
  "params": {
    "to": "cx0000000000000000000000000000000000000000",
    "dataType": "call",
    "data": {
      "method": "getPReps",
      "params": {
        "startRanking": "0x1",
        "endRanking": "0xaaa"
      }
    }
  }
}

How to pass array as parameter *on deploy* using goloop CLI ?

Hello,

I'd like to know if that's possible to pass an array as a parameter of goloop rpc sendtx deploy.
This issue is slightly related to #66 .

Right now the documentation only mentions a --param flag, but doesn't accept a --raw flag like goloop rpc call.

Is there an existing format for passing an array as a parameter using --param ?


Repro:

package com.iconloop.score.example;

import java.math.BigInteger;

import score.Context;
import score.ArrayDB;
import score.annotation.External;

public class HelloWorld {

    private final ArrayDB<BigInteger> array = Context.newArrayDB("array", BigInteger.class);

    public HelloWorld(BigInteger[] _array) {
        for (var item : _array) {
            this.array.add(item);
        }
    }

    @External(readonly = true)
    public BigInteger get_item (int index) {
        return this.array.get(index);
    }
}

Goloop CLIP command :

goloop rpc sendtx deploy helloworld-optimized.jar \
    --content_type application/java \
    --key_store ${key_store} \
    --key_password=${key_password} \
    --nid ${nid} \
    --step_limit ${step_limit} \
    --uri ${uri} \
    --param _array=???

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.