aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJeffrey Wilcke <jeffrey@ethereum.org>2015-05-20 17:31:52 +0800
committerJeffrey Wilcke <jeffrey@ethereum.org>2015-05-20 17:31:52 +0800
commit0300eef94d7d1e58bc5cf94094a3d492c70486e1 (patch)
treed2828b978ad2a0128459c9a09096aec95b18af1c
parent6b83a0a589d4615382de3d9f3ed2800064b4c1b9 (diff)
parente1d1417729b82f00bcb62dffa36358cb74ab790f (diff)
downloadgo-tangerine-0300eef94d7d1e58bc5cf94094a3d492c70486e1.tar
go-tangerine-0300eef94d7d1e58bc5cf94094a3d492c70486e1.tar.gz
go-tangerine-0300eef94d7d1e58bc5cf94094a3d492c70486e1.tar.bz2
go-tangerine-0300eef94d7d1e58bc5cf94094a3d492c70486e1.tar.lz
go-tangerine-0300eef94d7d1e58bc5cf94094a3d492c70486e1.tar.xz
go-tangerine-0300eef94d7d1e58bc5cf94094a3d492c70486e1.tar.zst
go-tangerine-0300eef94d7d1e58bc5cf94094a3d492c70486e1.zip
Merge pull request #1048 from ethersphere/cli-fixes
CLI, JSRE admin and Solc improvements
-rw-r--r--cmd/geth/admin.go25
-rw-r--r--cmd/geth/info_test.json2
-rw-r--r--cmd/geth/js.go3
-rw-r--r--cmd/geth/js_test.go44
-rw-r--r--cmd/geth/main.go12
-rw-r--r--cmd/utils/flags.go1
-rw-r--r--common/compiler/solidity.go110
-rw-r--r--common/compiler/solidity_test.go42
-rw-r--r--eth/backend.go20
-rw-r--r--jsre/ethereum_js.go2536
-rw-r--r--miner/worker.go1
-rw-r--r--rpc/api.go27
-rw-r--r--rpc/api_test.go44
-rw-r--r--rpc/args.go64
-rw-r--r--xeth/xeth.go19
15 files changed, 2305 insertions, 645 deletions
diff --git a/cmd/geth/admin.go b/cmd/geth/admin.go
index 53dd0e6ad..523b7c406 100644
--- a/cmd/geth/admin.go
+++ b/cmd/geth/admin.go
@@ -35,6 +35,7 @@ func (js *jsre) adminBindings() {
eth := ethO.Object()
eth.Set("pendingTransactions", js.pendingTransactions)
eth.Set("resend", js.resend)
+ eth.Set("sign", js.sign)
js.re.Set("admin", struct{}{})
t, _ := js.re.Get("admin")
@@ -177,6 +178,30 @@ func (js *jsre) resend(call otto.FunctionCall) otto.Value {
return otto.FalseValue()
}
+func (js *jsre) sign(call otto.FunctionCall) otto.Value {
+ if len(call.ArgumentList) != 2 {
+ fmt.Println("requires 2 arguments: eth.sign(signer, data)")
+ return otto.UndefinedValue()
+ }
+ signer, err := call.Argument(0).ToString()
+ if err != nil {
+ fmt.Println(err)
+ return otto.UndefinedValue()
+ }
+
+ data, err := call.Argument(1).ToString()
+ if err != nil {
+ fmt.Println(err)
+ return otto.UndefinedValue()
+ }
+ v, err := js.xeth.Sign(signer, data, false)
+ if err != nil {
+ fmt.Println(err)
+ return otto.UndefinedValue()
+ }
+ return js.re.ToVal(v)
+}
+
func (js *jsre) debugBlock(call otto.FunctionCall) otto.Value {
block, err := js.getBlock(call)
if err != nil {
diff --git a/cmd/geth/info_test.json b/cmd/geth/info_test.json
index 1e0c271ac..63f2163a9 100644
--- a/cmd/geth/info_test.json
+++ b/cmd/geth/info_test.json
@@ -1 +1 @@
-{"code":"605280600c6000396000f3006000357c010000000000000000000000000000000000000000000000000000000090048063c6888fa114602e57005b60376004356041565b8060005260206000f35b6000600782029050604d565b91905056","info":{"abiDefinition":[{"constant":false,"inputs":[{"name":"a","type":"uint256"}],"name":"multiply","outputs":[{"name":"d","type":"uint256"}],"type":"function"}],"compilerVersion":"0.9.17","developerDoc":{"methods":{}},"language":"Solidity","languageVersion":"0","source":"contract test {\n /// @notice Will multiply `a` by 7.\n function multiply(uint a) returns(uint d) {\n return a * 7;\n }\n}\n","userDoc":{"methods":{"multiply(uint256)":{"notice":"Will multiply `a` by 7."}}}}} \ No newline at end of file
+{"code":"0x605880600c6000396000f3006000357c010000000000000000000000000000000000000000000000000000000090048063c6888fa114602e57005b603d6004803590602001506047565b8060005260206000f35b60006007820290506053565b91905056","info":{"abiDefinition":[{"constant":false,"inputs":[{"name":"a","type":"uint256"}],"name":"multiply","outputs":[{"name":"d","type":"uint256"}],"type":"function"}],"compilerVersion":"0.9.23","developerDoc":{"methods":{}},"language":"Solidity","languageVersion":"0","source":"contract test {\n /// @notice Will multiply `a` by 7.\n function multiply(uint a) returns(uint d) {\n return a * 7;\n }\n}\n","userDoc":{"methods":{"multiply(uint256)":{"notice":"Will multiply `a` by 7."}}}}} \ No newline at end of file
diff --git a/cmd/geth/js.go b/cmd/geth/js.go
index 4ddb3bd9c..f99051a1e 100644
--- a/cmd/geth/js.go
+++ b/cmd/geth/js.go
@@ -71,7 +71,7 @@ type jsre struct {
prompter
}
-func newJSRE(ethereum *eth.Ethereum, libPath, solcPath, corsDomain string, interactive bool, f xeth.Frontend) *jsre {
+func newJSRE(ethereum *eth.Ethereum, libPath, corsDomain string, interactive bool, f xeth.Frontend) *jsre {
js := &jsre{ethereum: ethereum, ps1: "> "}
// set default cors domain used by startRpc from CLI flag
js.corsDomain = corsDomain
@@ -81,7 +81,6 @@ func newJSRE(ethereum *eth.Ethereum, libPath, solcPath, corsDomain string, inter
js.xeth = xeth.New(ethereum, f)
js.wait = js.xeth.UpdateState()
// update state in separare forever blocks
- js.xeth.SetSolc(solcPath)
js.re = re.New(libPath)
js.apiBindings(f)
js.adminBindings()
diff --git a/cmd/geth/js_test.go b/cmd/geth/js_test.go
index 6368efbfc..41e1034e9 100644
--- a/cmd/geth/js_test.go
+++ b/cmd/geth/js_test.go
@@ -24,7 +24,7 @@ import (
const (
testSolcPath = ""
- solcVersion = "0.9.17"
+ solcVersion = "0.9.23"
testKey = "e6fab74a43941f82d89cb7faa408e227cdad3153c4720e540e855c19b15e6674"
testAddress = "0x8605cdbbdb6d264aa742e77020dcbc58fcdce182"
@@ -34,6 +34,7 @@ const (
)
var (
+ versionRE = regexp.MustCompile(strconv.Quote(`"compilerVersion":"` + solcVersion + `"`))
testGenesis = `{"` + testAddress[2:] + `": {"balance": "` + testBalance + `"}}`
)
@@ -75,6 +76,7 @@ func testJEthRE(t *testing.T) (string, *testjethre, *eth.Ethereum) {
AccountManager: am,
MaxPeers: 0,
Name: "test",
+ SolcPath: testSolcPath,
})
if err != nil {
t.Fatal("%v", err)
@@ -101,7 +103,7 @@ func testJEthRE(t *testing.T) (string, *testjethre, *eth.Ethereum) {
t.Errorf("Error creating DocServer: %v", err)
}
tf := &testjethre{ds: ds, stateDb: ethereum.ChainManager().State().Copy()}
- repl := newJSRE(ethereum, assetPath, testSolcPath, "", false, tf)
+ repl := newJSRE(ethereum, assetPath, "", false, tf)
tf.jsre = repl
return tmp, tf, ethereum
}
@@ -228,11 +230,11 @@ func TestSignature(t *testing.T) {
defer ethereum.Stop()
defer os.RemoveAll(tmp)
- val, err := repl.re.Run(`eth.sign({from: "` + testAddress + `", data: "` + testHash + `"})`)
+ val, err := repl.re.Run(`eth.sign("` + testAddress + `", "` + testHash + `")`)
// This is a very preliminary test, lacking actual signature verification
if err != nil {
- t.Errorf("Error runnig js: %v", err)
+ t.Errorf("Error running js: %v", err)
return
}
output := val.String()
@@ -246,7 +248,6 @@ func TestSignature(t *testing.T) {
}
func TestContract(t *testing.T) {
- t.Skip()
tmp, repl, ethereum := testJEthRE(t)
if err := ethereum.Start(); err != nil {
@@ -259,7 +260,9 @@ func TestContract(t *testing.T) {
var txc uint64
coinbase := common.HexToAddress(testAddress)
resolver.New(repl.xeth).CreateContracts(coinbase)
+ // time.Sleep(1000 * time.Millisecond)
+ // checkEvalJSON(t, repl, `eth.getBlock("pending", true).transactions.length`, `2`)
source := `contract test {\n` +
" /// @notice Will multiply `a` by 7." + `\n` +
` function multiply(uint a) returns(uint d) {\n` +
@@ -279,10 +282,9 @@ func TestContract(t *testing.T) {
// if solc is found with right version, test it, otherwise read from file
sol, err := compiler.New("")
if err != nil {
- t.Logf("solc not found: skipping compiler test")
+ t.Logf("solc not found: mocking contract compilation step")
} else if sol.Version() != solcVersion {
- err = fmt.Errorf("solc wrong version found (%v, expect %v): skipping compiler test", sol.Version(), solcVersion)
- t.Log(err)
+ t.Logf("WARNING: solc different version found (%v, test written for %v, may need to update)", sol.Version(), solcVersion)
}
if err != nil {
@@ -295,10 +297,10 @@ func TestContract(t *testing.T) {
t.Errorf("%v", err)
}
} else {
- checkEvalJSON(t, repl, `contract = eth.compile.solidity(source)`, string(contractInfo))
+ checkEvalJSON(t, repl, `contract = eth.compile.solidity(source).test`, string(contractInfo))
}
- checkEvalJSON(t, repl, `contract.code`, `"605280600c6000396000f3006000357c010000000000000000000000000000000000000000000000000000000090048063c6888fa114602e57005b60376004356041565b8060005260206000f35b6000600782029050604d565b91905056"`)
+ checkEvalJSON(t, repl, `contract.code`, `"0x605880600c6000396000f3006000357c010000000000000000000000000000000000000000000000000000000090048063c6888fa114602e57005b603d6004803590602001506047565b8060005260206000f35b60006007820290506053565b91905056"`)
checkEvalJSON(
t, repl,
@@ -308,15 +310,16 @@ func TestContract(t *testing.T) {
callSetup := `abiDef = JSON.parse('[{"constant":false,"inputs":[{"name":"a","type":"uint256"}],"name":"multiply","outputs":[{"name":"d","type":"uint256"}],"type":"function"}]');
Multiply7 = eth.contract(abiDef);
-multiply7 = new Multiply7(contractaddress);
+multiply7 = Multiply7.at(contractaddress);
`
-
+ // time.Sleep(1500 * time.Millisecond)
_, err = repl.re.Run(callSetup)
if err != nil {
- t.Errorf("unexpected error registering, got %v", err)
+ t.Errorf("unexpected error setting up contract, got %v", err)
}
- // updatespec
+ // checkEvalJSON(t, repl, `eth.getBlock("pending", true).transactions.length`, `3`)
+
// why is this sometimes failing?
// checkEvalJSON(t, repl, `multiply7.multiply.call(6)`, `42`)
expNotice := ""
@@ -324,20 +327,23 @@ multiply7 = new Multiply7(contractaddress);
t.Errorf("incorrect confirmation message: expected %v, got %v", expNotice, repl.lastConfirm)
}
- // why 0?
- checkEvalJSON(t, repl, `eth.getBlock("pending", true).transactions.length`, `0`)
-
txc, repl.xeth = repl.xeth.ApplyTestTxs(repl.stateDb, coinbase, txc)
checkEvalJSON(t, repl, `admin.contractInfo.start()`, `true`)
checkEvalJSON(t, repl, `multiply7.multiply.sendTransaction(6, { from: primary, gas: "1000000", gasPrice: "100000" })`, `undefined`)
- expNotice = `About to submit transaction (no NatSpec info found for contract: content hash not found for '0x4a6c99e127191d2ee302e42182c338344b39a37a47cdbb17ab0f26b6802eb4d1'): {"params":[{"to":"0x5dcaace5982778b409c524873b319667eba5d074","data": "0xc6888fa10000000000000000000000000000000000000000000000000000000000000006"}]}`
+ expNotice = `About to submit transaction (no NatSpec info found for contract: content hash not found for '0x87e2802265838c7f14bb69eecd2112911af6767907a702eeaa445239fb20711b'): {"params":[{"to":"0x5dcaace5982778b409c524873b319667eba5d074","data": "0xc6888fa10000000000000000000000000000000000000000000000000000000000000006"}]}`
if repl.lastConfirm != expNotice {
t.Errorf("incorrect confirmation message: expected %v, got %v", expNotice, repl.lastConfirm)
}
+ var contenthash = `"0x86d2b7cf1e72e9a7a3f8d96601f0151742a2f780f1526414304fbe413dc7f9bd"`
+ if sol != nil {
+ modContractInfo := versionRE.ReplaceAll(contractInfo, []byte(`"compilerVersion":"`+sol.Version()+`"`))
+ _ = modContractInfo
+ // contenthash = crypto.Sha3(modContractInfo)
+ }
checkEvalJSON(t, repl, `filename = "/tmp/info.json"`, `"/tmp/info.json"`)
- checkEvalJSON(t, repl, `contenthash = admin.contractInfo.register(primary, contractaddress, contract, filename)`, `"0x0d067e2dd99a4d8f0c0279738b17130dd415a89f24a23f0e7cf68c546ae3089d"`)
+ checkEvalJSON(t, repl, `contenthash = admin.contractInfo.register(primary, contractaddress, contract, filename)`, contenthash)
checkEvalJSON(t, repl, `admin.contractInfo.registerUrl(primary, contenthash, "file://"+filename)`, `true`)
if err != nil {
t.Errorf("unexpected error registering, got %v", err)
diff --git a/cmd/geth/main.go b/cmd/geth/main.go
index 2afc92f10..ba253bbeb 100644
--- a/cmd/geth/main.go
+++ b/cmd/geth/main.go
@@ -99,7 +99,15 @@ The output of this command is supposed to be machine-readable.
Usage: "import ethereum presale wallet",
},
},
- },
+ Description: `
+
+ get wallet import /path/to/my/presale.wallet
+
+will prompt for your password and imports your ether presale account.
+It can be used non-interactively with the --password option taking a
+passwordfile as argument containing the wallet password in plaintext.
+
+`},
{
Action: accountList,
Name: "account",
@@ -326,7 +334,6 @@ func console(ctx *cli.Context) {
repl := newJSRE(
ethereum,
ctx.String(utils.JSpathFlag.Name),
- ctx.String(utils.SolcPathFlag.Name),
ctx.GlobalString(utils.RPCCORSDomainFlag.Name),
true,
nil,
@@ -348,7 +355,6 @@ func execJSFiles(ctx *cli.Context) {
repl := newJSRE(
ethereum,
ctx.String(utils.JSpathFlag.Name),
- ctx.String(utils.SolcPathFlag.Name),
ctx.GlobalString(utils.RPCCORSDomainFlag.Name),
false,
nil,
diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go
index f646e4fcc..2766e7517 100644
--- a/cmd/utils/flags.go
+++ b/cmd/utils/flags.go
@@ -313,6 +313,7 @@ func MakeEthConfig(clientID, version string, ctx *cli.Context) *eth.Config {
Dial: true,
BootNodes: ctx.GlobalString(BootnodesFlag.Name),
GasPrice: common.String2Big(ctx.GlobalString(GasPriceFlag.Name)),
+ SolcPath: ctx.GlobalString(SolcPathFlag.Name),
}
}
diff --git a/common/compiler/solidity.go b/common/compiler/solidity.go
index 6790f9a1d..0cfd41c95 100644
--- a/common/compiler/solidity.go
+++ b/common/compiler/solidity.go
@@ -18,7 +18,8 @@ import (
)
const (
- flair = "Christian <c@ethdev.com> and Lefteris <lefteris@ethdev.com> (c) 2014-2015"
+ // flair = "Christian <c@ethdev.com> and Lefteris <lefteris@ethdev.com> (c) 2014-2015"
+ flair = ""
languageVersion = "0"
)
@@ -91,7 +92,7 @@ func (sol *Solidity) Version() string {
return sol.version
}
-func (sol *Solidity) Compile(source string) (contract *Contract, err error) {
+func (sol *Solidity) Compile(source string) (contracts map[string]*Contract, err error) {
if len(source) == 0 {
err = fmt.Errorf("empty source")
@@ -122,58 +123,61 @@ func (sol *Solidity) Compile(source string) (contract *Contract, err error) {
err = fmt.Errorf("solc error: missing code output")
return
}
- if len(matches) > 1 {
- err = fmt.Errorf("multi-contract sources are not supported")
- return
- }
- _, file := filepath.Split(matches[0])
- base := strings.Split(file, ".")[0]
-
- codeFile := filepath.Join(wd, base+".binary")
- abiDefinitionFile := filepath.Join(wd, base+".abi")
- userDocFile := filepath.Join(wd, base+".docuser")
- developerDocFile := filepath.Join(wd, base+".docdev")
- code, err := ioutil.ReadFile(codeFile)
- if err != nil {
- err = fmt.Errorf("error reading compiler output for code: %v", err)
- return
- }
- abiDefinitionJson, err := ioutil.ReadFile(abiDefinitionFile)
- if err != nil {
- err = fmt.Errorf("error reading compiler output for abiDefinition: %v", err)
- return
- }
- var abiDefinition interface{}
- err = json.Unmarshal(abiDefinitionJson, &abiDefinition)
-
- userDocJson, err := ioutil.ReadFile(userDocFile)
- if err != nil {
- err = fmt.Errorf("error reading compiler output for userDoc: %v", err)
- return
- }
- var userDoc interface{}
- err = json.Unmarshal(userDocJson, &userDoc)
-
- developerDocJson, err := ioutil.ReadFile(developerDocFile)
- if err != nil {
- err = fmt.Errorf("error reading compiler output for developerDoc: %v", err)
- return
- }
- var developerDoc interface{}
- err = json.Unmarshal(developerDocJson, &developerDoc)
-
- contract = &Contract{
- Code: string(code),
- Info: ContractInfo{
- Source: source,
- Language: "Solidity",
- LanguageVersion: languageVersion,
- CompilerVersion: sol.version,
- AbiDefinition: abiDefinition,
- UserDoc: userDoc,
- DeveloperDoc: developerDoc,
- },
+ contracts = make(map[string]*Contract)
+ for _, path := range matches {
+ _, file := filepath.Split(path)
+ base := strings.Split(file, ".")[0]
+
+ codeFile := filepath.Join(wd, base+".binary")
+ abiDefinitionFile := filepath.Join(wd, base+".abi")
+ userDocFile := filepath.Join(wd, base+".docuser")
+ developerDocFile := filepath.Join(wd, base+".docdev")
+
+ var code, abiDefinitionJson, userDocJson, developerDocJson []byte
+ code, err = ioutil.ReadFile(codeFile)
+ if err != nil {
+ err = fmt.Errorf("error reading compiler output for code: %v", err)
+ return
+ }
+ abiDefinitionJson, err = ioutil.ReadFile(abiDefinitionFile)
+ if err != nil {
+ err = fmt.Errorf("error reading compiler output for abiDefinition: %v", err)
+ return
+ }
+ var abiDefinition interface{}
+ err = json.Unmarshal(abiDefinitionJson, &abiDefinition)
+
+ userDocJson, err = ioutil.ReadFile(userDocFile)
+ if err != nil {
+ err = fmt.Errorf("error reading compiler output for userDoc: %v", err)
+ return
+ }
+ var userDoc interface{}
+ err = json.Unmarshal(userDocJson, &userDoc)
+
+ developerDocJson, err = ioutil.ReadFile(developerDocFile)
+ if err != nil {
+ err = fmt.Errorf("error reading compiler output for developerDoc: %v", err)
+ return
+ }
+ var developerDoc interface{}
+ err = json.Unmarshal(developerDocJson, &developerDoc)
+
+ contract := &Contract{
+ Code: "0x" + string(code),
+ Info: ContractInfo{
+ Source: source,
+ Language: "Solidity",
+ LanguageVersion: languageVersion,
+ CompilerVersion: sol.version,
+ AbiDefinition: abiDefinition,
+ UserDoc: userDoc,
+ DeveloperDoc: developerDoc,
+ },
+ }
+
+ contracts[base] = contract
}
return
diff --git a/common/compiler/solidity_test.go b/common/compiler/solidity_test.go
index 68e54a7ec..46f733e59 100644
--- a/common/compiler/solidity_test.go
+++ b/common/compiler/solidity_test.go
@@ -9,7 +9,7 @@ import (
"github.com/ethereum/go-ethereum/common"
)
-const solcVersion = "0.9.17"
+const solcVersion = "0.9.23"
var (
source = `
@@ -20,37 +20,45 @@ contract test {
}
}
`
- code = "605280600c6000396000f3006000357c010000000000000000000000000000000000000000000000000000000090048063c6888fa114602e57005b60376004356041565b8060005260206000f35b6000600782029050604d565b91905056"
- info = `{"source":"\ncontract test {\n /// @notice Will multiply ` + "`a`" + ` by 7.\n function multiply(uint a) returns(uint d) {\n return a * 7;\n }\n}\n","language":"Solidity","languageVersion":"0","compilerVersion":"0.9.17","abiDefinition":[{"constant":false,"inputs":[{"name":"a","type":"uint256"}],"name":"multiply","outputs":[{"name":"d","type":"uint256"}],"type":"function"}],"userDoc":{"methods":{"multiply(uint256)":{"notice":"Will multiply ` + "`a`" + ` by 7."}}},"developerDoc":{"methods":{}}}`
+ code = "0x605880600c6000396000f3006000357c010000000000000000000000000000000000000000000000000000000090048063c6888fa114602e57005b603d6004803590602001506047565b8060005260206000f35b60006007820290506053565b91905056"
+ info = `{"source":"\ncontract test {\n /// @notice Will multiply ` + "`a`" + ` by 7.\n function multiply(uint a) returns(uint d) {\n return a * 7;\n }\n}\n","language":"Solidity","languageVersion":"0","compilerVersion":"0.9.23","abiDefinition":[{"constant":false,"inputs":[{"name":"a","type":"uint256"}],"name":"multiply","outputs":[{"name":"d","type":"uint256"}],"type":"function"}],"userDoc":{"methods":{"multiply(uint256)":{"notice":"Will multiply ` + "`a`" + ` by 7."}}},"developerDoc":{"methods":{}}}`
- infohash = common.HexToHash("0x834075768a68e500e459b9c3213750c84de3df47156500cb01bb664d3f88c60a")
+ infohash = common.HexToHash("0xea782f674eb898e477c20e8a7cf11c2c28b09fa68b5278732104f7a101aed255")
)
func TestCompiler(t *testing.T) {
sol, err := New("")
if err != nil {
- t.Skip("no solc installed")
+ t.Skip("solc not found: skip")
+ } else if sol.Version() != solcVersion {
+ t.Logf("WARNING: a newer version of solc found (%v, expect %v)", sol.Version(), solcVersion)
}
- contract, err := sol.Compile(source)
+ contracts, err := sol.Compile(source)
if err != nil {
- t.Errorf("error compiling source. result %v: %v", contract, err)
+ t.Errorf("error compiling source. result %v: %v", contracts, err)
return
}
- /*
- if contract.Code != code {
- t.Errorf("wrong code, expected\n%s, got\n%s", code, contract.Code)
- }
- */
+
+ if len(contracts) != 1 {
+ t.Errorf("one contract expected, got\n%s", len(contracts))
+ }
+
+ if contracts["test"].Code != code {
+ t.Errorf("wrong code, expected\n%s, got\n%s", code, contracts["test"].Code)
+ }
+
}
func TestCompileError(t *testing.T) {
sol, err := New("")
if err != nil || sol.version != solcVersion {
- t.Skip("no solc installed")
+ t.Skip("solc not found: skip")
+ } else if sol.Version() != solcVersion {
+ t.Logf("WARNING: a newer version of solc found (%v, expect %v)", sol.Version(), solcVersion)
}
- contract, err := sol.Compile(source[2:])
+ contracts, err := sol.Compile(source[2:])
if err == nil {
- t.Errorf("error expected compiling source. got none. result %v", contract)
+ t.Errorf("error expected compiling source. got none. result %v", contracts)
return
}
}
@@ -78,11 +86,11 @@ func TestExtractInfo(t *testing.T) {
os.Remove(filename)
cinfohash, err := ExtractInfo(contract, filename)
if err != nil {
- t.Errorf("%v", err)
+ t.Errorf("error extracting info: %v", err)
}
got, err := ioutil.ReadFile(filename)
if err != nil {
- t.Errorf("%v", err)
+ t.Errorf("error reading '%v': %v", filename, err)
}
if string(got) != info {
t.Errorf("incorrect info.json extracted, expected:\n%s\ngot\n%s", info, string(got))
diff --git a/eth/backend.go b/eth/backend.go
index 519a4c410..44ceb89e8 100644
--- a/eth/backend.go
+++ b/eth/backend.go
@@ -14,6 +14,7 @@ import (
"github.com/ethereum/ethash"
"github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/common/compiler"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
@@ -79,6 +80,7 @@ type Config struct {
GasPrice *big.Int
MinerThreads int
AccountManager *accounts.Manager
+ SolcPath string
// NewDB is used to create databases.
// If nil, the default is to create leveldb databases on disk.
@@ -181,6 +183,8 @@ type Ethereum struct {
pow *ethash.Ethash
protocolManager *ProtocolManager
downloader *downloader.Downloader
+ SolcPath string
+ solc *compiler.Solidity
net *p2p.Server
eventMux *event.TypeMux
@@ -264,6 +268,7 @@ func New(config *Config) (*Ethereum, error) {
netVersionId: config.NetworkId,
NatSpec: config.NatSpec,
MinerThreads: config.MinerThreads,
+ SolcPath: config.SolcPath,
}
eth.pow = ethash.New()
@@ -571,3 +576,18 @@ func saveBlockchainVersion(db common.Database, bcVersion int) {
db.Put([]byte("BlockchainVersion"), common.NewValue(bcVersion).Bytes())
}
}
+
+func (self *Ethereum) Solc() (*compiler.Solidity, error) {
+ var err error
+ if self.solc == nil {
+ self.solc, err = compiler.New(self.SolcPath)
+ }
+ return self.solc, err
+}
+
+// set in js console via admin interface or wrapper from cli flags
+func (self *Ethereum) SetSolc(solcPath string) (*compiler.Solidity, error) {
+ self.SolcPath = solcPath
+ self.solc = nil
+ return self.Solc()
+}
diff --git a/jsre/ethereum_js.go b/jsre/ethereum_js.go
index a61ffcbbf..6c0ae33d7 100644
--- a/jsre/ethereum_js.go
+++ b/jsre/ethereum_js.go
@@ -1,7 +1,6 @@
package jsre
-const Ethereum_JS = `
-require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
+const Ethereum_JS = `require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
/*
This file is part of ethereum.js.
@@ -18,142 +17,7 @@ require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof requ
You should have received a copy of the GNU Lesser General Public License
along with ethereum.js. If not, see <http://www.gnu.org/licenses/>.
*/
-/**
- * @file abi.js
- * @author Marek Kotewicz <marek@ethdev.com>
- * @author Gav Wood <g@ethdev.com>
- * @date 2014
- */
-
-var utils = require('../utils/utils');
-var coder = require('./coder');
-var solUtils = require('./utils');
-
-/**
- * Formats input params to bytes
- *
- * @method formatInput
- * @param {Array} abi inputs of method
- * @param {Array} params that will be formatted to bytes
- * @returns bytes representation of input params
- */
-var formatInput = function (inputs, params) {
- var i = inputs.map(function (input) {
- return input.type;
- });
- return coder.encodeParams(i, params);
-};
-
-/**
- * Formats output bytes back to param list
- *
- * @method formatOutput
- * @param {Array} abi outputs of method
- * @param {String} bytes represention of output
- * @returns {Array} output params
- */
-var formatOutput = function (outs, bytes) {
- var o = outs.map(function (out) {
- return out.type;
- });
-
- return coder.decodeParams(o, bytes);
-};
-
/**
- * Should be called to create input parser for contract with given abi
- *
- * @method inputParser
- * @param {Array} contract abi
- * @returns {Object} input parser object for given json abi
- * TODO: refactor creating the parser, do not double logic from contract
- */
-var inputParser = function (json) {
- var parser = {};
- json.forEach(function (method) {
- var displayName = utils.extractDisplayName(method.name);
- var typeName = utils.extractTypeName(method.name);
-
- var impl = function () {
- var params = Array.prototype.slice.call(arguments);
- return formatInput(method.inputs, params);
- };
-
- if (parser[displayName] === undefined) {
- parser[displayName] = impl;
- }
-
- parser[displayName][typeName] = impl;
- });
-
- return parser;
-};
-
-/**
- * Should be called to create output parser for contract with given abi
- *
- * @method outputParser
- * @param {Array} contract abi
- * @returns {Object} output parser for given json abi
- */
-var outputParser = function (json) {
- var parser = {};
- json.forEach(function (method) {
-
- var displayName = utils.extractDisplayName(method.name);
- var typeName = utils.extractTypeName(method.name);
-
- var impl = function (output) {
- return formatOutput(method.outputs, output);
- };
-
- if (parser[displayName] === undefined) {
- parser[displayName] = impl;
- }
-
- parser[displayName][typeName] = impl;
- });
-
- return parser;
-};
-
-var formatConstructorParams = function (abi, params) {
- var constructor = solUtils.getConstructor(abi, params.length);
- if (!constructor) {
- if (params.length > 0) {
- console.warn("didn't found matching constructor, using default one");
- }
- return '';
- }
- return formatInput(constructor.inputs, params);
-};
-
-module.exports = {
- inputParser: inputParser,
- outputParser: outputParser,
- formatInput: formatInput,
- formatOutput: formatOutput,
- formatConstructorParams: formatConstructorParams
-};
-
-},{"../utils/utils":8,"./coder":2,"./utils":5}],2:[function(require,module,exports){
-/*
- This file is part of ethereum.js.
-
- ethereum.js is free software: you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- ethereum.js is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with ethereum.js. If not, see <http://www.gnu.org/licenses/>.
-*/
-/**
* @file coder.js
* @author Marek Kotewicz <marek@ethdev.com>
* @date 2015
@@ -208,7 +72,7 @@ SolidityType.prototype.isType = function (name) {
* @method formatInput
* @param {Object} param - plain object, or an array of objects
* @param {Bool} arrayType - true if a param should be encoded as an array
- * @return {SolidityParam} encoded param wrapped in SolidityParam object
+ * @return {SolidityParam} encoded param wrapped in SolidityParam object
*/
SolidityType.prototype.formatInput = function (param, arrayType) {
if (utils.isArray(param) && arrayType) { // TODO: should fail if this two are not the same
@@ -216,10 +80,9 @@ SolidityType.prototype.formatInput = function (param, arrayType) {
return param.map(function (p) {
return self._inputFormatter(p);
}).reduce(function (acc, current) {
- acc.appendArrayElement(current);
- return acc;
- }, new SolidityParam(f.formatInputInt(param.length).value));
- }
+ return acc.combine(current);
+ }, f.formatInputInt(param.length)).withOffset(32);
+ }
return this._inputFormatter(param);
};
@@ -233,11 +96,11 @@ SolidityType.prototype.formatInput = function (param, arrayType) {
*/
SolidityType.prototype.formatOutput = function (param, arrayType) {
if (arrayType) {
- // let's assume, that we solidity will never return long arrays :P
+ // let's assume, that we solidity will never return long arrays :P
var result = [];
- var length = new BigNumber(param.value, 16);
+ var length = new BigNumber(param.dynamicPart().slice(0, 64), 16);
for (var i = 0; i < length * 64; i += 64) {
- result.push(this._outputFormatter(new SolidityParam(param.suffix.slice(i, i + 64))));
+ result.push(this._outputFormatter(new SolidityParam(param.dynamicPart().substr(i + 64, 64))));
}
return result;
}
@@ -245,31 +108,21 @@ SolidityType.prototype.formatOutput = function (param, arrayType) {
};
/**
- * Should be used to check if a type is variadic
- *
- * @method isVariadicType
- * @param {String} type
- * @returns {Bool} true if the type is variadic
- */
-SolidityType.prototype.isVariadicType = function (type) {
- return isArrayType(type) || this._mode === 'bytes';
-};
-
-/**
- * Should be used to shift param from params group
+ * Should be used to slice single param from bytes
*
- * @method shiftParam
+ * @method sliceParam
+ * @param {String} bytes
+ * @param {Number} index of param to slice
* @param {String} type
- * @returns {SolidityParam} shifted param
+ * @returns {SolidityParam} param
*/
-SolidityType.prototype.shiftParam = function (type, param) {
+SolidityType.prototype.sliceParam = function (bytes, index, type) {
if (this._mode === 'bytes') {
- return param.shiftBytes();
+ return SolidityParam.decodeBytes(bytes, index);
} else if (isArrayType(type)) {
- var length = new BigNumber(param.value.slice(0, 64), 16);
- return param.shiftArray(length);
+ return SolidityParam.decodeArray(bytes, index);
}
- return param.shiftValue();
+ return SolidityParam.decodeParam(bytes, index);
};
/**
@@ -284,7 +137,7 @@ var SolidityCoder = function (types) {
*
* @method _requireType
* @param {String} type
- * @returns {SolidityType}
+ * @returns {SolidityType}
* @throws {Error} throws if no matching type is found
*/
SolidityCoder.prototype._requireType = function (type) {
@@ -300,20 +153,6 @@ SolidityCoder.prototype._requireType = function (type) {
};
/**
- * Should be used to transform plain bytes to SolidityParam object
- *
- * @method _bytesToParam
- * @param {Array} types of params
- * @param {String} bytes to be transformed to SolidityParam
- * @return {SolidityParam} SolidityParam for this group of params
- */
-SolidityCoder.prototype._bytesToParam = function (types, bytes) {
- var value = bytes.slice(0, types.length * 64);
- var suffix = bytes.slice(types.length * 64);
- return new SolidityParam(value, suffix);
-};
-
-/**
* Should be used to transform plain param of given type to SolidityParam
*
* @method _formatInput
@@ -347,24 +186,11 @@ SolidityCoder.prototype.encodeParam = function (type, param) {
*/
SolidityCoder.prototype.encodeParams = function (types, params) {
var self = this;
- return types.map(function (type, index) {
+ var solidityParams = types.map(function (type, index) {
return self._formatInput(type, params[index]);
- }).reduce(function (acc, solidityParam) {
- acc.append(solidityParam);
- return acc;
- }, new SolidityParam()).encode();
-};
+ });
-/**
- * Should be used to transform SolidityParam to plain param
- *
- * @method _formatOutput
- * @param {String} type
- * @param {SolidityParam} param
- * @return {Object} plain param
- */
-SolidityCoder.prototype._formatOutput = function (type, param) {
- return this._requireType(type).formatOutput(param, isArrayType(type));
+ return SolidityParam.encodeList(solidityParams);
};
/**
@@ -376,7 +202,7 @@ SolidityCoder.prototype._formatOutput = function (type, param) {
* @return {Object} plain param
*/
SolidityCoder.prototype.decodeParam = function (type, bytes) {
- return this._formatOutput(type, this._bytesToParam([type], bytes));
+ return this.decodeParams([type], bytes)[0];
};
/**
@@ -389,10 +215,9 @@ SolidityCoder.prototype.decodeParam = function (type, bytes) {
*/
SolidityCoder.prototype.decodeParams = function (types, bytes) {
var self = this;
- var param = this._bytesToParam(types, bytes);
- return types.map(function (type) {
+ return types.map(function (type, index) {
var solidityType = self._requireType(type);
- var p = solidityType.shiftParam(type, param);
+ var p = solidityType.sliceParam(bytes, index, type);
return solidityType.formatOutput(p, isArrayType(type));
});
};
@@ -459,7 +284,7 @@ var coder = new SolidityCoder([
module.exports = coder;
-},{"../utils/utils":8,"./formatters":3,"./param":4,"bignumber.js":"bignumber.js"}],3:[function(require,module,exports){
+},{"../utils/utils":7,"./formatters":2,"./param":3,"bignumber.js":"bignumber.js"}],2:[function(require,module,exports){
/*
This file is part of ethereum.js.
@@ -476,7 +301,7 @@ module.exports = coder;
You should have received a copy of the GNU Lesser General Public License
along with ethereum.js. If not, see <http://www.gnu.org/licenses/>.
*/
-/**
+/**
* @file formatters.js
* @author Marek Kotewicz <marek@ethdev.com>
* @date 2015
@@ -525,7 +350,7 @@ var formatInputBytes = function (value) {
*/
var formatInputDynamicBytes = function (value) {
var result = utils.fromAscii(value, c.ETH_PADDING).substr(2);
- return new SolidityParam(formatInputInt(value.length).value, result);
+ return new SolidityParam(formatInputInt(value.length).value + result, 32);
};
/**
@@ -571,7 +396,7 @@ var signedIsNegative = function (value) {
* @returns {BigNumber} right-aligned output bytes formatted to big number
*/
var formatOutputInt = function (param) {
- var value = param.value || "0";
+ var value = param.staticPart() || "0";
// check if it's negative number
// it it is, return two's complement
@@ -589,7 +414,7 @@ var formatOutputInt = function (param) {
* @returns {BigNumeber} right-aligned output bytes formatted to uint
*/
var formatOutputUInt = function (param) {
- var value = param.value || "0";
+ var value = param.staticPart() || "0";
return new BigNumber(value, 16);
};
@@ -601,7 +426,7 @@ var formatOutputUInt = function (param) {
* @returns {BigNumber} input bytes formatted to real
*/
var formatOutputReal = function (param) {
- return formatOutputInt(param).dividedBy(new BigNumber(2).pow(128));
+ return formatOutputInt(param).dividedBy(new BigNumber(2).pow(128));
};
/**
@@ -612,7 +437,7 @@ var formatOutputReal = function (param) {
* @returns {BigNumber} input bytes formatted to ureal
*/
var formatOutputUReal = function (param) {
- return formatOutputUInt(param).dividedBy(new BigNumber(2).pow(128));
+ return formatOutputUInt(param).dividedBy(new BigNumber(2).pow(128));
};
/**
@@ -623,7 +448,7 @@ var formatOutputUReal = function (param) {
* @returns {Boolean} right-aligned input bytes formatted to bool
*/
var formatOutputBool = function (param) {
- return param.value === '0000000000000000000000000000000000000000000000000000000000000001' ? true : false;
+ return param.staticPart() === '0000000000000000000000000000000000000000000000000000000000000001' ? true : false;
};
/**
@@ -635,7 +460,7 @@ var formatOutputBool = function (param) {
*/
var formatOutputBytes = function (param) {
// length might also be important!
- return utils.toAscii(param.value);
+ return utils.toAscii(param.staticPart());
};
/**
@@ -647,7 +472,7 @@ var formatOutputBytes = function (param) {
*/
var formatOutputDynamicBytes = function (param) {
// length might also be important!
- return utils.toAscii(param.suffix);
+ return utils.toAscii(param.dynamicPart().slice(64));
};
/**
@@ -658,7 +483,7 @@ var formatOutputDynamicBytes = function (param) {
* @returns {String} address
*/
var formatOutputAddress = function (param) {
- var value = param.value;
+ var value = param.staticPart();
return "0x" + value.slice(value.length - 40, value.length);
};
@@ -679,7 +504,7 @@ module.exports = {
};
-},{"../utils/config":7,"../utils/utils":8,"./param":4,"bignumber.js":"bignumber.js"}],4:[function(require,module,exports){
+},{"../utils/config":5,"../utils/utils":7,"./param":3,"bignumber.js":"bignumber.js"}],3:[function(require,module,exports){
/*
This file is part of ethereum.js.
@@ -696,136 +521,202 @@ module.exports = {
You should have received a copy of the GNU Lesser General Public License
along with ethereum.js. If not, see <http://www.gnu.org/licenses/>.
*/
-/**
+/**
* @file param.js
* @author Marek Kotewicz <marek@ethdev.com>
* @date 2015
*/
+var utils = require('../utils/utils');
+
/**
* SolidityParam object prototype.
* Should be used when encoding, decoding solidity bytes
*/
-var SolidityParam = function (value, suffix) {
+var SolidityParam = function (value, offset) {
this.value = value || '';
- this.suffix = suffix || '';
+ this.offset = offset; // offset in bytes
};
/**
- * This method should be used to encode two params one after another
+ * This method should be used to get length of params's dynamic part
*
- * @method append
- * @param {SolidityParam} param that it appended after this
+ * @method dynamicPartLength
+ * @returns {Number} length of dynamic part (in bytes)
*/
-SolidityParam.prototype.append = function (param) {
- this.value += param.value;
- this.suffix += param.suffix;
+SolidityParam.prototype.dynamicPartLength = function () {
+ return this.dynamicPart().length / 2;
};
/**
- * This method should be used to encode next param in an array
+ * This method should be used to create copy of solidity param with different offset
*
- * @method appendArrayElement
- * @param {SolidityParam} param that is appended to an array
+ * @method withOffset
+ * @param {Number} offset length in bytes
+ * @returns {SolidityParam} new solidity param with applied offset
*/
-SolidityParam.prototype.appendArrayElement = function (param) {
- this.suffix += param.value;
- //this.suffix += param.suffix; // we do not support nested dynamic types
+SolidityParam.prototype.withOffset = function (offset) {
+ return new SolidityParam(this.value, offset);
};
/**
- * This method should be used to create bytearrays from param
+ * This method should be used to combine solidity params together
+ * eg. when appending an array
*
- * @method encode
- * @return {String} encoded param(s)
+ * @method combine
+ * @param {SolidityParam} param with which we should combine
+ * @param {SolidityParam} result of combination
*/
-SolidityParam.prototype.encode = function () {
- return this.value + this.suffix;
+SolidityParam.prototype.combine = function (param) {
+ return new SolidityParam(this.value + param.value);
};
/**
- * This method should be used to shift first param from group of params
+ * This method should be called to check if param has dynamic size.
+ * If it has, it returns true, otherwise false
*
- * @method shiftValue
- * @return {SolidityParam} first value param
+ * @method isDynamic
+ * @returns {Boolean}
*/
-SolidityParam.prototype.shiftValue = function () {
- var value = this.value.slice(0, 64);
- this.value = this.value.slice(64);
- return new SolidityParam(value);
+SolidityParam.prototype.isDynamic = function () {
+ return this.value.length > 64;
};
/**
- * This method should be used to first bytes param from group of params
+ * This method should be called to transform offset to bytes
*
- * @method shiftBytes
- * @return {SolidityParam} first bytes param
+ * @method offsetAsBytes
+ * @returns {String} bytes representation of offset
*/
-SolidityParam.prototype.shiftBytes = function () {
- return this.shiftArray(1);
+SolidityParam.prototype.offsetAsBytes = function () {
+ return !this.isDynamic() ? '' : utils.padLeft(utils.toTwosComplement(this.offset).toString(16), 64);
};
/**
- * This method should be used to shift an array from group of params
- *
- * @method shiftArray
- * @param {Number} size of an array to shift
- * @return {SolidityParam} first array param
+ * This method should be called to get static part of param
+ *
+ * @method staticPart
+ * @returns {String} offset if it is a dynamic param, otherwise value
*/
-SolidityParam.prototype.shiftArray = function (length) {
- var value = this.value.slice(0, 64);
- this.value = this.value.slice(64);
- var suffix = this.suffix.slice(0, 64 * length);
- this.suffix = this.suffix.slice(64 * length);
- return new SolidityParam(value, suffix);
+SolidityParam.prototype.staticPart = function () {
+ if (!this.isDynamic()) {
+ return this.value;
+ }
+ return this.offsetAsBytes();
};
-module.exports = SolidityParam;
+/**
+ * This method should be called to get dynamic part of param
+ *
+ * @method dynamicPart
+ * @returns {String} returns a value if it is a dynamic param, otherwise empty string
+ */
+SolidityParam.prototype.dynamicPart = function () {
+ return this.isDynamic() ? this.value : '';
+};
+/**
+ * This method should be called to encode param
+ *
+ * @method encode
+ * @returns {String}
+ */
+SolidityParam.prototype.encode = function () {
+ return this.staticPart() + this.dynamicPart();
+};
-},{}],5:[function(require,module,exports){
-/*
- This file is part of ethereum.js.
+/**
+ * This method should be called to encode array of params
+ *
+ * @method encodeList
+ * @param {Array[SolidityParam]} params
+ * @returns {String}
+ */
+SolidityParam.encodeList = function (params) {
- ethereum.js is free software: you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
+ // updating offsets
+ var totalOffset = params.length * 32;
+ var offsetParams = params.map(function (param) {
+ if (!param.isDynamic()) {
+ return param;
+ }
+ var offset = totalOffset;
+ totalOffset += param.dynamicPartLength();
+ return param.withOffset(offset);
+ });
- ethereum.js is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Lesser General Public License for more details.
+ // encode everything!
+ return offsetParams.reduce(function (result, param) {
+ return result + param.dynamicPart();
+ }, offsetParams.reduce(function (result, param) {
+ return result + param.staticPart();
+ }, ''));
+};
- You should have received a copy of the GNU Lesser General Public License
- along with ethereum.js. If not, see <http://www.gnu.org/licenses/>.
-*/
/**
- * @file utils.js
- * @author Marek Kotewicz <marek@ethdev.com>
- * @date 2015
+ * This method should be used to decode plain (static) solidity param at given index
+ *
+ * @method decodeParam
+ * @param {String} bytes
+ * @param {Number} index
+ * @returns {SolidityParam}
*/
+SolidityParam.decodeParam = function (bytes, index) {
+ index = index || 0;
+ return new SolidityParam(bytes.substr(index * 64, 64));
+};
/**
- * Returns the contstructor with matching number of arguments
+ * This method should be called to get offset value from bytes at given index
*
- * @method getConstructor
- * @param {Array} abi
- * @param {Number} numberOfArgs
- * @returns {Object} constructor function abi
+ * @method getOffset
+ * @param {String} bytes
+ * @param {Number} index
+ * @returns {Number} offset as number
*/
-var getConstructor = function (abi, numberOfArgs) {
- return abi.filter(function (f) {
- return f.type === 'constructor' && f.inputs.length === numberOfArgs;
- })[0];
+var getOffset = function (bytes, index) {
+ // we can do this cause offset is rather small
+ return parseInt('0x' + bytes.substr(index * 64, 64));
};
-module.exports = {
- getConstructor: getConstructor
+/**
+ * This method should be called to decode solidity bytes param at given index
+ *
+ * @method decodeBytes
+ * @param {String} bytes
+ * @param {Number} index
+ * @returns {SolidityParam}
+ */
+SolidityParam.decodeBytes = function (bytes, index) {
+ index = index || 0;
+ //TODO add support for strings longer than 32 bytes
+ //var length = parseInt('0x' + bytes.substr(offset * 64, 64));
+
+ var offset = getOffset(bytes, index);
+
+ // 2 * , cause we also parse length
+ return new SolidityParam(bytes.substr(offset * 2, 2 * 64));
};
+/**
+ * This method should be used to decode solidity array at given index
+ *
+ * @method decodeArray
+ * @param {String} bytes
+ * @param {Number} index
+ * @returns {SolidityParam}
+ */
+SolidityParam.decodeArray = function (bytes, index) {
+ index = index || 0;
+ var offset = getOffset(bytes, index);
+ var length = parseInt('0x' + bytes.substr(offset * 2, 64));
+ return new SolidityParam(bytes.substr(offset * 2, (length + 1) * 64));
+};
+
+module.exports = SolidityParam;
+
-},{}],6:[function(require,module,exports){
+},{"../utils/utils":7}],4:[function(require,module,exports){
'use strict';
// go env doesn't have and need XMLHttpRequest
@@ -836,7 +727,7 @@ if (typeof XMLHttpRequest === 'undefined') {
}
-},{}],7:[function(require,module,exports){
+},{}],5:[function(require,module,exports){
/*
This file is part of ethereum.js.
@@ -861,13 +752,13 @@ if (typeof XMLHttpRequest === 'undefined') {
/**
* Utils
- *
+ *
* @module utils
*/
/**
* Utility functions
- *
+ *
* @class [utils] config
* @constructor
*/
@@ -875,26 +766,26 @@ if (typeof XMLHttpRequest === 'undefined') {
/// required to define ETH_BIGNUMBER_ROUNDING_MODE
var BigNumber = require('bignumber.js');
-var ETH_UNITS = [
- 'wei',
- 'Kwei',
- 'Mwei',
- 'Gwei',
- 'szabo',
- 'finney',
- 'ether',
- 'grand',
- 'Mether',
- 'Gether',
- 'Tether',
- 'Pether',
- 'Eether',
- 'Zether',
- 'Yether',
- 'Nether',
- 'Dether',
- 'Vether',
- 'Uether'
+var ETH_UNITS = [
+ 'wei',
+ 'Kwei',
+ 'Mwei',
+ 'Gwei',
+ 'szabo',
+ 'finney',
+ 'ether',
+ 'grand',
+ 'Mether',
+ 'Gether',
+ 'Tether',
+ 'Pether',
+ 'Eether',
+ 'Zether',
+ 'Yether',
+ 'Nether',
+ 'Dether',
+ 'Vether',
+ 'Uether'
];
module.exports = {
@@ -908,7 +799,7 @@ module.exports = {
};
-},{"bignumber.js":"bignumber.js"}],8:[function(require,module,exports){
+},{"bignumber.js":"bignumber.js"}],6:[function(require,module,exports){
/*
This file is part of ethereum.js.
@@ -925,7 +816,39 @@ module.exports = {
You should have received a copy of the GNU Lesser General Public License
along with ethereum.js. If not, see <http://www.gnu.org/licenses/>.
*/
-/**
+/**
+ * @file sha3.js
+ * @author Marek Kotewicz <marek@ethdev.com>
+ * @date 2015
+ */
+
+var sha3 = require('crypto-js/sha3');
+
+module.exports = function (str) {
+ return sha3(str, {
+ outputLength: 256
+ }).toString();
+};
+
+
+},{"crypto-js/sha3":30}],7:[function(require,module,exports){
+/*
+ This file is part of ethereum.js.
+
+ ethereum.js is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ ethereum.js is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with ethereum.js. If not, see <http://www.gnu.org/licenses/>.
+*/
+/**
* @file utils.js
* @author Marek Kotewicz <marek@ethdev.com>
* @date 2015
@@ -933,13 +856,13 @@ module.exports = {
/**
* Utils
- *
+ *
* @module utils
*/
/**
* Utility functions
- *
+ *
* @class [utils] utils
* @constructor
*/
@@ -978,7 +901,7 @@ var padLeft = function (string, chars, sign) {
return new Array(chars - string.length + 1).join(sign ? sign : "0") + string;
};
-/**
+/**
* Should be called to get sting from it's hex representation
*
* @method toAscii
@@ -1003,9 +926,9 @@ var toAscii = function(hex) {
return str;
};
-
+
/**
- * Shold be called to get hex representation (prefixed by 0x) of ascii string
+ * Shold be called to get hex representation (prefixed by 0x) of ascii string
*
* @method toHexNative
* @param {String} string
@@ -1022,7 +945,7 @@ var toHexNative = function(str) {
};
/**
- * Shold be called to get hex representation (prefixed by 0x) of ascii string
+ * Shold be called to get hex representation (prefixed by 0x) of ascii string
*
* @method fromAscii
* @param {String} string
@@ -1055,13 +978,13 @@ var transformToFullName = function (json) {
/**
* Should be called to get display name of contract function
- *
+ *
* @method extractDisplayName
* @param {String} name of function/event
* @returns {String} display name for function/event eg. multiply(uint256) -> multiply
*/
var extractDisplayName = function (name) {
- var length = name.indexOf('(');
+ var length = name.indexOf('(');
return length !== -1 ? name.substr(0, length) : name;
};
@@ -1169,7 +1092,7 @@ var getValueOfUnit = function (unit) {
var fromWei = function(number, unit) {
var returnValue = toBigNumber(number).dividedBy(getValueOfUnit(unit));
- return isBigNumber(number) ? returnValue : returnValue.toString(10);
+ return isBigNumber(number) ? returnValue : returnValue.toString(10);
};
/**
@@ -1195,7 +1118,7 @@ var fromWei = function(number, unit) {
var toWei = function(number, unit) {
var returnValue = toBigNumber(number).times(getValueOfUnit(unit));
- return isBigNumber(number) ? returnValue : returnValue.toString(10);
+ return isBigNumber(number) ? returnValue : returnValue.toString(10);
};
/**
@@ -1214,7 +1137,7 @@ var toBigNumber = function(number) {
if (isString(number) && (number.indexOf('0x') === 0 || number.indexOf('-0x') === 0)) {
return new BigNumber(number.replace('0x',''), 16);
}
-
+
return new BigNumber(number.toString(10), 10);
};
@@ -1266,7 +1189,7 @@ var toAddress = function (address) {
if (isStrictAddress(address)) {
return address;
}
-
+
if (/^[0-9a-f]{40}$/.test(address)) {
return '0x' + address;
}
@@ -1274,12 +1197,13 @@ var toAddress = function (address) {
return '0x' + padLeft(toHex(address).substr(2), 40);
};
+
/**
* Returns true if object is BigNumber, otherwise false
*
* @method isBigNumber
* @param {Object}
- * @return {Boolean}
+ * @return {Boolean}
*/
var isBigNumber = function (object) {
return object instanceof BigNumber ||
@@ -1288,7 +1212,7 @@ var isBigNumber = function (object) {
/**
* Returns true if object is string, otherwise false
- *
+ *
* @method isString
* @param {Object}
* @return {Boolean}
@@ -1339,12 +1263,12 @@ var isBoolean = function (object) {
* @return {Boolean}
*/
var isArray = function (object) {
- return object instanceof Array;
+ return object instanceof Array;
};
/**
* Returns true if given string is valid json object
- *
+ *
* @method isJson
* @param {String}
* @return {Boolean}
@@ -1384,12 +1308,12 @@ module.exports = {
};
-},{"bignumber.js":"bignumber.js"}],9:[function(require,module,exports){
+},{"bignumber.js":"bignumber.js"}],8:[function(require,module,exports){
module.exports={
- "version": "0.3.5"
+ "version": "0.4.2"
}
-},{}],10:[function(require,module,exports){
+},{}],9:[function(require,module,exports){
/*
This file is part of ethereum.js.
@@ -1427,16 +1351,9 @@ var utils = require('./utils/utils');
var formatters = require('./web3/formatters');
var RequestManager = require('./web3/requestmanager');
var c = require('./utils/config');
-var Method = require('./web3/method');
var Property = require('./web3/property');
-
-var web3Methods = [
- new Method({
- name: 'sha3',
- call: 'web3_sha3',
- params: 1
- })
-];
+var Batch = require('./web3/batch');
+var sha3 = require('./utils/sha3');
var web3Properties = [
new Property({
@@ -1521,6 +1438,10 @@ web3.toBigNumber = utils.toBigNumber;
web3.toWei = utils.toWei;
web3.fromWei = utils.fromWei;
web3.isAddress = utils.isAddress;
+web3.sha3 = sha3;
+web3.createBatch = function () {
+ return new Batch();
+};
// ADD defaultblock
Object.defineProperty(web3.eth, 'defaultBlock', {
@@ -1544,7 +1465,6 @@ Object.defineProperty(web3.eth, 'defaultAccount', {
});
/// setups all api methods
-setupMethods(web3, web3Methods);
setupProperties(web3, web3Properties);
setupMethods(web3.net, net.methods);
setupProperties(web3.net, net.properties);
@@ -1556,7 +1476,7 @@ setupMethods(web3.shh, shh.methods);
module.exports = web3;
-},{"./utils/config":7,"./utils/utils":8,"./version.json":9,"./web3/db":12,"./web3/eth":14,"./web3/filter":16,"./web3/formatters":17,"./web3/method":21,"./web3/net":22,"./web3/property":23,"./web3/requestmanager":25,"./web3/shh":26,"./web3/watches":27}],11:[function(require,module,exports){
+},{"./utils/config":5,"./utils/sha3":6,"./utils/utils":7,"./version.json":8,"./web3/batch":10,"./web3/db":12,"./web3/eth":14,"./web3/filter":16,"./web3/formatters":17,"./web3/net":22,"./web3/property":23,"./web3/requestmanager":25,"./web3/shh":26,"./web3/watches":27}],10:[function(require,module,exports){
/*
This file is part of ethereum.js.
@@ -1573,20 +1493,109 @@ module.exports = web3;
You should have received a copy of the GNU Lesser General Public License
along with ethereum.js. If not, see <http://www.gnu.org/licenses/>.
*/
-/**
+/**
+ * @file batch.js
+ * @author Marek Kotewicz <marek@ethdev.com>
+ * @date 2015
+ */
+
+var RequestManager = require('./requestmanager');
+
+var Batch = function () {
+ this.requests = [];
+};
+
+/**
+ * Should be called to add create new request to batch request
+ *
+ * @method add
+ * @param {Object} jsonrpc requet object
+ */
+Batch.prototype.add = function (request) {
+ this.requests.push(request);
+};
+
+/**
+ * Should be called to execute batch request
+ *
+ * @method execute
+ */
+Batch.prototype.execute = function () {
+ var requests = this.requests;
+ RequestManager.getInstance().sendBatch(requests, function (err, results) {
+ results = results || [];
+ requests.map(function (request, index) {
+ return results[index] || {};
+ }).map(function (result, index) {
+ return requests[index].format ? requests[index].format(result.result) : result.result;
+ }).forEach(function (result, index) {
+ if (requests[index].callback) {
+ requests[index].callback(err, result);
+ }
+ });
+ });
+};
+
+module.exports = Batch;
+
+
+},{"./requestmanager":25}],11:[function(require,module,exports){
+/*
+ This file is part of ethereum.js.
+
+ ethereum.js is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ ethereum.js is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with ethereum.js. If not, see <http://www.gnu.org/licenses/>.
+*/
+/**
* @file contract.js
* @author Marek Kotewicz <marek@ethdev.com>
* @date 2014
*/
-var web3 = require('../web3');
-var solAbi = require('../solidity/abi');
+var web3 = require('../web3');
var utils = require('../utils/utils');
+var coder = require('../solidity/coder');
var SolidityEvent = require('./event');
var SolidityFunction = require('./function');
-var addFunctionsToContract = function (contract, desc) {
- desc.filter(function (json) {
+/**
+ * Should be called to encode constructor params
+ *
+ * @method encodeConstructorParams
+ * @param {Array} abi
+ * @param {Array} constructor params
+ */
+var encodeConstructorParams = function (abi, params) {
+ return abi.filter(function (json) {
+ return json.type === 'constructor' && json.inputs.length === params.length;
+ }).map(function (json) {
+ return json.inputs.map(function (input) {
+ return input.type;
+ });
+ }).map(function (types) {
+ return coder.encodeParams(types, params);
+ })[0] || '';
+};
+
+/**
+ * Should be called to add functions to contract object
+ *
+ * @method addFunctionsToContract
+ * @param {Contract} contract
+ * @param {Array} abi
+ */
+var addFunctionsToContract = function (contract, abi) {
+ abi.filter(function (json) {
return json.type === 'function';
}).map(function (json) {
return new SolidityFunction(json, contract.address);
@@ -1595,8 +1604,15 @@ var addFunctionsToContract = function (contract, desc) {
});
};
-var addEventsToContract = function (contract, desc) {
- desc.filter(function (json) {
+/**
+ * Should be called to add events to contract object
+ *
+ * @method addEventsToContract
+ * @param {Contract} contract
+ * @param {Array} abi
+ */
+var addEventsToContract = function (contract, abi) {
+ abi.filter(function (json) {
return json.type === 'event';
}).map(function (json) {
return new SolidityEvent(json, contract.address);
@@ -1606,65 +1622,106 @@ var addEventsToContract = function (contract, desc) {
};
/**
- * This method should be called when we want to call / transact some solidity method from javascript
- * it returns an object which has same methods available as solidity contract description
- * usage example:
- *
- * var abi = [{
- * name: 'myMethod',
- * inputs: [{ name: 'a', type: 'string' }],
- * outputs: [{name: 'd', type: 'string' }]
- * }]; // contract abi
- *
- * var MyContract = web3.eth.contract(abi); // creation of contract prototype
- *
- * var contractInstance = new MyContract('0x0123123121');
- *
- * contractInstance.myMethod('this is test string param for call'); // myMethod call (implicit, default)
- * contractInstance.call().myMethod('this is test string param for call'); // myMethod call (explicit)
- * contractInstance.sendTransaction().myMethod('this is test string param for transact'); // myMethod sendTransaction
+ * Should be called to create new ContractFactory
*
- * @param abi - abi json description of the contract, which is being created
- * @returns contract object
+ * @method contract
+ * @param {Array} abi
+ * @returns {ContractFactory} new contract factory
*/
var contract = function (abi) {
+ return new ContractFactory(abi);
+};
- // return prototype
- return Contract.bind(null, abi);
+/**
+ * Should be called to create new ContractFactory instance
+ *
+ * @method ContractFactory
+ * @param {Array} abi
+ */
+var ContractFactory = function (abi) {
+ this.abi = abi;
};
-var Contract = function (abi, options) {
+/**
+ * Should be called to create new contract on a blockchain
+ *
+ * @method new
+ * @param {Any} contract constructor param1 (optional)
+ * @param {Any} contract constructor param2 (optional)
+ * @param {Object} contract transaction object (required)
+ * @param {Function} callback
+ * @returns {Contract} returns contract if no callback was passed,
+ * otherwise calls callback function (err, contract)
+ */
+ContractFactory.prototype.new = function () {
+ // parse arguments
+ var options = {}; // required!
+ var callback;
- this.address = '';
- if (utils.isAddress(options)) {
- this.address = options;
- } else { // is an object!
- // TODO, parse the rest of the args
- options = options || {};
- var args = Array.prototype.slice.call(arguments, 2);
- var bytes = solAbi.formatConstructorParams(abi, args);
- options.data += bytes;
- this.address = web3.eth.sendTransaction(options);
+ var args = Array.prototype.slice.call(arguments);
+ if (utils.isFunction(args[args.length - 1])) {
+ callback = args.pop();
}
- addFunctionsToContract(this, abi);
- addEventsToContract(this, abi);
+ var last = args[args.length - 1];
+ if (utils.isObject(last) && !utils.isArray(last)) {
+ options = args.pop();
+ }
+
+ // throw an error if there are no options
+
+ var bytes = encodeConstructorParams(this.abi, args);
+ options.data += bytes;
+
+ if (!callback) {
+ var address = web3.eth.sendTransaction(options);
+ return this.at(address);
+ }
+
+ var self = this;
+ web3.eth.sendTransaction(options, function (err, address) {
+ if (err) {
+ callback(err);
+ }
+ self.at(address, callback);
+ });
};
-Contract.prototype.call = function () {
- console.error('contract.call is deprecated');
- return this;
+/**
+ * Should be called to get access to existing contract on a blockchain
+ *
+ * @method at
+ * @param {Address} contract address (required)
+ * @param {Function} callback {optional)
+ * @returns {Contract} returns contract if no callback was passed,
+ * otherwise calls callback function (err, contract)
+ */
+ContractFactory.prototype.at = function (address, callback) {
+ // TODO: address is required
+
+ if (callback) {
+ callback(null, new Contract(this.abi, address));
+ }
+ return new Contract(this.abi, address);
};
-Contract.prototype.sendTransaction = function () {
- console.error('contract.sendTransact is deprecated');
- return this;
+/**
+ * Should be called to create new contract instance
+ *
+ * @method Contract
+ * @param {Array} abi
+ * @param {Address} contract address
+ */
+var Contract = function (abi, address) {
+ this.address = address;
+ addFunctionsToContract(this, abi);
+ addEventsToContract(this, abi);
};
module.exports = contract;
-},{"../solidity/abi":1,"../utils/utils":8,"../web3":10,"./event":15,"./function":18}],12:[function(require,module,exports){
+},{"../solidity/coder":1,"../utils/utils":7,"../web3":9,"./event":15,"./function":18}],12:[function(require,module,exports){
/*
This file is part of ethereum.js.
@@ -1739,7 +1796,7 @@ module.exports = {
You should have received a copy of the GNU Lesser General Public License
along with ethereum.js. If not, see <http://www.gnu.org/licenses/>.
*/
-/**
+/**
* @file errors.js
* @author Marek Kotewicz <marek@ethdev.com>
* @date 2015
@@ -1925,12 +1982,6 @@ var getTransactionCount = new Method({
outputFormatter: utils.toDecimal
});
-var sign = new Method({
- name: 'sign',
- call: 'eth_sign',
- params: 1
-});
-
var sendTransaction = new Method({
name: 'sendTransaction',
call: 'eth_sendTransaction',
@@ -1945,6 +1996,14 @@ var call = new Method({
inputFormatter: [formatters.inputTransactionFormatter, formatters.inputDefaultBlockNumberFormatter]
});
+var estimateGas = new Method({
+ name: 'estimateGas',
+ call: 'eth_estimateGas',
+ params: 1,
+ inputFormatter: [formatters.inputTransactionFormatter],
+ outputFormatter: utils.toDecimal
+});
+
var compileSolidity = new Method({
name: 'compile.solidity',
call: 'eth_compileSolidity',
@@ -1963,6 +2022,18 @@ var compileSerpent = new Method({
params: 1
});
+var submitWork = new Method({
+ name: 'submitWork',
+ call: 'eth_submitWork',
+ params: 3
+});
+
+var getWork = new Method({
+ name: 'getWork',
+ call: 'eth_getWork',
+ params: 0
+});
+
var methods = [
getBalance,
getStorageAt,
@@ -1976,11 +2047,13 @@ var methods = [
getTransactionFromBlock,
getTransactionCount,
call,
- sign,
+ estimateGas,
sendTransaction,
compileSolidity,
compileLLL,
compileSerpent,
+ submitWork,
+ getWork
];
/// @returns an array of objects describing web3.eth api properties
@@ -2023,7 +2096,7 @@ module.exports = {
};
-},{"../utils/utils":8,"./formatters":17,"./method":21,"./property":23}],15:[function(require,module,exports){
+},{"../utils/utils":7,"./formatters":17,"./method":21,"./property":23}],15:[function(require,module,exports){
/*
This file is part of ethereum.js.
@@ -2040,7 +2113,7 @@ module.exports = {
You should have received a copy of the GNU Lesser General Public License
along with ethereum.js. If not, see <http://www.gnu.org/licenses/>.
*/
-/**
+/**
* @file event.js
* @author Marek Kotewicz <marek@ethdev.com>
* @date 2014
@@ -2050,6 +2123,7 @@ var utils = require('../utils/utils');
var coder = require('../solidity/coder');
var web3 = require('../web3');
var formatters = require('./formatters');
+var sha3 = require('../utils/sha3');
/**
* This prototype should be used to create event filters
@@ -2103,12 +2177,12 @@ SolidityEvent.prototype.typeName = function () {
* @return {String} event signature
*/
SolidityEvent.prototype.signature = function () {
- return web3.sha3(web3.fromAscii(this._name)).slice(2);
+ return sha3(this._name);
};
/**
* Should be used to encode indexed params and options to one final object
- *
+ *
* @method encode
* @param {Object} indexed
* @param {Object} options
@@ -2139,7 +2213,7 @@ SolidityEvent.prototype.encode = function (indexed, options) {
if (value === undefined || value === null) {
return null;
}
-
+
if (utils.isArray(value)) {
return value.map(function (v) {
return '0x' + coder.encodeParam(i.type, v);
@@ -2161,17 +2235,17 @@ SolidityEvent.prototype.encode = function (indexed, options) {
* @return {Object} result object with decoded indexed && not indexed params
*/
SolidityEvent.prototype.decode = function (data) {
-
+
data.data = data.data || '';
data.topics = data.topics || [];
var argTopics = this._anonymous ? data.topics : data.topics.slice(1);
var indexedData = argTopics.map(function (topics) { return topics.slice(2); }).join("");
- var indexedParams = coder.decodeParams(this.types(true), indexedData);
+ var indexedParams = coder.decodeParams(this.types(true), indexedData);
var notIndexedData = data.data.slice(2);
var notIndexedParams = coder.decodeParams(this.types(false), notIndexedData);
-
+
var result = formatters.outputLogFormatter(data);
result.event = this.displayName();
result.address = data.address;
@@ -2219,7 +2293,7 @@ SolidityEvent.prototype.attachToContract = function (contract) {
module.exports = SolidityEvent;
-},{"../solidity/coder":2,"../utils/utils":8,"../web3":10,"./formatters":17}],16:[function(require,module,exports){
+},{"../solidity/coder":1,"../utils/sha3":6,"../utils/utils":7,"../web3":9,"./formatters":17}],16:[function(require,module,exports){
/*
This file is part of ethereum.js.
@@ -2276,7 +2350,7 @@ var getOptions = function (options) {
if (utils.isString(options)) {
return options;
- }
+ }
options = options || {};
@@ -2292,8 +2366,8 @@ var getOptions = function (options) {
to: options.to,
address: options.address,
fromBlock: formatters.inputBlockNumberFormatter(options.fromBlock),
- toBlock: formatters.inputBlockNumberFormatter(options.toBlock)
- };
+ toBlock: formatters.inputBlockNumberFormatter(options.toBlock)
+ };
};
var Filter = function (options, methods, formatter) {
@@ -2376,7 +2450,7 @@ Filter.prototype.get = function (callback) {
module.exports = Filter;
-},{"../utils/utils":8,"./formatters":17,"./requestmanager":25}],17:[function(require,module,exports){
+},{"../utils/utils":7,"./formatters":17,"./requestmanager":25}],17:[function(require,module,exports){
/*
This file is part of ethereum.js.
@@ -2393,7 +2467,7 @@ module.exports = Filter;
You should have received a copy of the GNU Lesser General Public License
along with ethereum.js. If not, see <http://www.gnu.org/licenses/>.
*/
-/**
+/**
* @file formatters.js
* @author Marek Kotewicz <marek@ethdev.com>
* @author Fabian Vogelsteller <fabian@ethdev.com>
@@ -2451,18 +2525,18 @@ var inputTransactionFormatter = function (options){
delete options.code;
}
- ['gasPrice', 'gas', 'value'].filter(function (key) {
+ ['gasPrice', 'gas', 'value', 'nonce'].filter(function (key) {
return options[key] !== undefined;
}).forEach(function(key){
options[key] = utils.fromDecimal(options[key]);
});
- return options;
+ return options;
};
/**
* Formats the output of a transaction to its proper values
- *
+ *
* @method outputTransactionFormatter
* @param {Object} transaction
* @returns {Object} transaction
@@ -2481,7 +2555,7 @@ var outputTransactionFormatter = function (tx){
* Formats the output of a block to its proper values
*
* @method outputBlockFormatter
- * @param {Object} block object
+ * @param {Object} block object
* @returns {Object} block object
*/
var outputBlockFormatter = function(block) {
@@ -2508,7 +2582,7 @@ var outputBlockFormatter = function(block) {
/**
* Formats the output of a log
- *
+ *
* @method outputLogFormatter
* @param {Object} log object
* @returns {Object} log
@@ -2549,7 +2623,7 @@ var inputPostFormatter = function(post) {
return utils.fromAscii(topic);
});
- return post;
+ return post;
};
/**
@@ -2596,7 +2670,7 @@ module.exports = {
};
-},{"../utils/config":7,"../utils/utils":8}],18:[function(require,module,exports){
+},{"../utils/config":5,"../utils/utils":7}],18:[function(require,module,exports){
/*
This file is part of ethereum.js.
@@ -2613,7 +2687,7 @@ module.exports = {
You should have received a copy of the GNU Lesser General Public License
along with ethereum.js. If not, see <http://www.gnu.org/licenses/>.
*/
-/**
+/**
* @file function.js
* @author Marek Kotewicz <marek@ethdev.com>
* @date 2015
@@ -2622,6 +2696,7 @@ module.exports = {
var web3 = require('../web3');
var coder = require('../solidity/coder');
var utils = require('../utils/utils');
+var sha3 = require('../utils/sha3');
/**
* This prototype should be used to call/sendTransaction to solidity functions
@@ -2638,18 +2713,23 @@ var SolidityFunction = function (json, address) {
this._address = address;
};
+SolidityFunction.prototype.extractCallback = function (args) {
+ if (utils.isFunction(args[args.length - 1])) {
+ return args.pop(); // modify the args array!
+ }
+};
+
/**
* Should be used to create payload from arguments
*
* @method toPayload
- * @param {...} solidity function params
+ * @param {Array} solidity function params
* @param {Object} optional payload options
*/
-SolidityFunction.prototype.toPayload = function () {
- var args = Array.prototype.slice.call(arguments);
+SolidityFunction.prototype.toPayload = function (args) {
var options = {};
if (args.length > this._inputTypes.length && utils.isObject(args[args.length -1])) {
- options = args.pop();
+ options = args[args.length - 1];
}
options.to = this._address;
options.data = '0x' + this.signature() + coder.encodeParams(this._inputTypes, args);
@@ -2663,22 +2743,44 @@ SolidityFunction.prototype.toPayload = function () {
* @return {String} function signature
*/
SolidityFunction.prototype.signature = function () {
- return web3.sha3(web3.fromAscii(this._name)).slice(2, 10);
+ return sha3(this._name).slice(0, 8);
+};
+
+
+SolidityFunction.prototype.unpackOutput = function (output) {
+ if (output === null) {
+ return;
+ }
+
+ output = output.length >= 2 ? output.slice(2) : output;
+ var result = coder.decodeParams(this._outputTypes, output);
+ return result.length === 1 ? result[0] : result;
};
/**
- * Should be used to call function
- *
+ * Calls a contract function.
+ *
* @method call
- * @param {Object} options
+ * @param {...Object} Contract function arguments
+ * @param {function} If the last argument is a function, the contract function
+ * call will be asynchronous, and the callback will be passed the
+ * error and result.
* @return {String} output bytes
*/
SolidityFunction.prototype.call = function () {
- var payload = this.toPayload.apply(this, Array.prototype.slice.call(arguments));
- var output = web3.eth.call(payload);
- output = output.length >= 2 ? output.slice(2) : output;
- var result = coder.decodeParams(this._outputTypes, output);
- return result.length === 1 ? result[0] : result;
+ var args = Array.prototype.slice.call(arguments);
+ var callback = this.extractCallback(args);
+ var payload = this.toPayload(args);
+
+ if (!callback) {
+ var output = web3.eth.call(payload);
+ return this.unpackOutput(output);
+ }
+
+ var self = this;
+ web3.eth.call(payload, function (error, output) {
+ callback(error, self.unpackOutput(output));
+ });
};
/**
@@ -2688,8 +2790,16 @@ SolidityFunction.prototype.call = function () {
* @param {Object} options
*/
SolidityFunction.prototype.sendTransaction = function () {
- var payload = this.toPayload.apply(this, Array.prototype.slice.call(arguments));
- web3.eth.sendTransaction(payload);
+ var args = Array.prototype.slice.call(arguments);
+ var callback = this.extractCallback(args);
+ var payload = this.toPayload(args);
+
+ if (!callback) {
+ web3.eth.sendTransaction(payload);
+ return;
+ }
+
+ web3.eth.sendTransaction(payload, callback);
};
/**
@@ -2704,7 +2814,7 @@ SolidityFunction.prototype.displayName = function () {
/**
* Should be used to get function type name
- *
+ *
* @method typeName
* @return {String} type name of the function
*/
@@ -2713,13 +2823,32 @@ SolidityFunction.prototype.typeName = function () {
};
/**
+ * Should be called to get rpc requests from solidity function
+ *
+ * @method request
+ * @returns {Object}
+ */
+SolidityFunction.prototype.request = function () {
+ var args = Array.prototype.slice.call(arguments);
+ var callback = this.extractCallback(args);
+ var payload = this.toPayload(args);
+ var format = this.unpackOutput.bind(this);
+
+ return {
+ callback: callback,
+ payload: payload,
+ format: format
+ };
+};
+
+/**
* Should be called to execute function
*
* @method execute
*/
SolidityFunction.prototype.execute = function () {
var transaction = !this._constant;
-
+
// send transaction
if (transaction) {
return this.sendTransaction.apply(this, Array.prototype.slice.call(arguments));
@@ -2737,6 +2866,7 @@ SolidityFunction.prototype.execute = function () {
*/
SolidityFunction.prototype.attachToContract = function (contract) {
var execute = this.execute.bind(this);
+ execute.request = this.request.bind(this);
execute.call = this.call.bind(this);
execute.sendTransaction = this.sendTransaction.bind(this);
var displayName = this.displayName();
@@ -2749,7 +2879,7 @@ SolidityFunction.prototype.attachToContract = function (contract) {
module.exports = SolidityFunction;
-},{"../solidity/coder":2,"../utils/utils":8,"../web3":10}],19:[function(require,module,exports){
+},{"../solidity/coder":1,"../utils/sha3":6,"../utils/utils":7,"../web3":9}],19:[function(require,module,exports){
/*
This file is part of ethereum.js.
@@ -2787,7 +2917,7 @@ HttpProvider.prototype.send = function (payload) {
var request = new XMLHttpRequest();
request.open('POST', this.host, false);
-
+
try {
request.send(JSON.stringify(payload));
} catch(error) {
@@ -2800,15 +2930,32 @@ HttpProvider.prototype.send = function (payload) {
//if (request.status !== 200) {
//return;
//}
- return JSON.parse(request.responseText);
+
+ var result = request.responseText;
+
+ try {
+ result = JSON.parse(result);
+ } catch(e) {
+ throw errors.InvalidResponse(result);
+ }
+
+ return result;
};
HttpProvider.prototype.sendAsync = function (payload, callback) {
var request = new XMLHttpRequest();
request.onreadystatechange = function() {
if (request.readyState === 4) {
- // TODO: handle the error properly here!!!
- callback(null, JSON.parse(request.responseText));
+ var result = request.responseText;
+ var error = null;
+
+ try {
+ result = JSON.parse(result);
+ } catch(e) {
+ error = errors.InvalidResponse(result);
+ }
+
+ callback(error, result);
}
};
@@ -2824,7 +2971,7 @@ HttpProvider.prototype.sendAsync = function (payload, callback) {
module.exports = HttpProvider;
-},{"./errors":13,"xmlhttprequest":6}],20:[function(require,module,exports){
+},{"./errors":13,"xmlhttprequest":4}],20:[function(require,module,exports){
/*
This file is part of ethereum.js.
@@ -2974,12 +3121,11 @@ Method.prototype.extractCallback = function (args) {
if (utils.isFunction(args[args.length - 1])) {
return args.pop(); // modify the args array!
}
- return null;
};
/**
* Should be called to check if the number of arguments is correct
- *
+ *
* @method validateArgs
* @param {Array} arguments
* @throws {Error} if it is not
@@ -2992,7 +3138,7 @@ Method.prototype.validateArgs = function (args) {
/**
* Should be called to format input args of method
- *
+ *
* @method formatInput
* @param {Array}
* @return {Array}
@@ -3020,20 +3166,21 @@ Method.prototype.formatOutput = function (result) {
/**
* Should attach function to method
- *
+ *
* @method attachToObject
* @param {Object}
* @param {Function}
*/
Method.prototype.attachToObject = function (obj) {
var func = this.send.bind(this);
+ func.request = this.request.bind(this);
func.call = this.call; // that's ugly. filter.js uses it
var name = this.name.split('.');
if (name.length > 1) {
obj[name[0]] = obj[name[0]] || {};
obj[name[0]][name[1]] = func;
} else {
- obj[name[0]] = func;
+ obj[name[0]] = func;
}
};
@@ -3058,6 +3205,19 @@ Method.prototype.toPayload = function (args) {
};
/**
+ * Should be called to create pure JSONRPC request which can be used in batch request
+ *
+ * @method request
+ * @param {...} params
+ * @return {Object} jsonrpc request
+ */
+Method.prototype.request = function () {
+ var payload = this.toPayload(Array.prototype.slice.call(arguments));
+ payload.format = this.formatOutput.bind(this);
+ return payload;
+};
+
+/**
* Should send request to the API
*
* @method send
@@ -3069,7 +3229,7 @@ Method.prototype.send = function () {
if (payload.callback) {
var self = this;
return RequestManager.getInstance().sendAsync(payload, function (err, result) {
- payload.callback(null, self.formatOutput(result));
+ payload.callback(err, self.formatOutput(result));
});
}
return this.formatOutput(RequestManager.getInstance().send(payload));
@@ -3078,7 +3238,7 @@ Method.prototype.send = function () {
module.exports = Method;
-},{"../utils/utils":8,"./errors":13,"./requestmanager":25}],22:[function(require,module,exports){
+},{"../utils/utils":7,"./errors":13,"./requestmanager":25}],22:[function(require,module,exports){
/*
This file is part of ethereum.js.
@@ -3128,7 +3288,7 @@ module.exports = {
};
-},{"../utils/utils":8,"./property":23}],23:[function(require,module,exports){
+},{"../utils/utils":7,"./property":23}],23:[function(require,module,exports){
/*
This file is part of ethereum.js.
@@ -3164,7 +3324,7 @@ var Property = function (options) {
/**
* Should be called to format input args of method
- *
+ *
* @method formatInput
* @param {Array}
* @return {Array}
@@ -3186,7 +3346,7 @@ Property.prototype.formatOutput = function (result) {
/**
* Should attach function to method
- *
+ *
* @method attachToObject
* @param {Object}
* @param {Function}
@@ -3194,16 +3354,23 @@ Property.prototype.formatOutput = function (result) {
Property.prototype.attachToObject = function (obj) {
var proto = {
get: this.get.bind(this),
- set: this.set.bind(this)
};
- var name = this.name.split('.');
- if (name.length > 1) {
- obj[name[0]] = obj[name[0]] || {};
- Object.defineProperty(obj[name[0]], name[1], proto);
- } else {
- Object.defineProperty(obj, name[0], proto);
+ var names = this.name.split('.');
+ var name = names[0];
+ if (names.length > 1) {
+ obj[names[0]] = obj[names[0]] || {};
+ obj = obj[names[0]];
+ name = names[1];
}
+
+ Object.defineProperty(obj, name, proto);
+
+ var toAsyncName = function (prefix, name) {
+ return prefix + name.charAt(0).toUpperCase() + name.slice(1);
+ };
+
+ obj[toAsyncName('get', name)] = this.getAsync.bind(this);
};
/**
@@ -3219,15 +3386,20 @@ Property.prototype.get = function () {
};
/**
- * Should be used to set value of the property
+ * Should be used to asynchrounously get value of property
*
- * @method set
- * @param {Object} new value of the property
+ * @method getAsync
+ * @param {Function}
*/
-Property.prototype.set = function (value) {
- return RequestManager.getInstance().send({
- method: this.setter,
- params: [this.formatInput(value)]
+Property.prototype.getAsync = function (callback) {
+ var self = this;
+ RequestManager.getInstance().sendAsync({
+ method: this.getter
+ }, function (err, result) {
+ if (err) {
+ return callback(err);
+ }
+ callback(err, self.formatOutput(result));
});
};
@@ -3286,7 +3458,7 @@ module.exports = QtSyncProvider;
You should have received a copy of the GNU Lesser General Public License
along with ethereum.js. If not, see <http://www.gnu.org/licenses/>.
*/
-/**
+/**
* @file requestmanager.js
* @author Jeffrey Wilcke <jeff@ethdev.com>
* @author Marek Kotewicz <marek@ethdev.com>
@@ -3368,7 +3540,7 @@ RequestManager.prototype.sendAsync = function (data, callback) {
if (err) {
return callback(err);
}
-
+
if (!Jsonrpc.getInstance().isValidResponse(result)) {
return callback(errors.InvalidResponse(result));
}
@@ -3378,6 +3550,33 @@ RequestManager.prototype.sendAsync = function (data, callback) {
};
/**
+ * Should be called to asynchronously send batch request
+ *
+ * @method sendBatch
+ * @param {Array} batch data
+ * @param {Function} callback
+ */
+RequestManager.prototype.sendBatch = function (data, callback) {
+ if (!this.provider) {
+ return callback(errors.InvalidProvider());
+ }
+
+ var payload = Jsonrpc.getInstance().toBatchPayload(data);
+
+ this.provider.sendAsync(payload, function (err, results) {
+ if (err) {
+ return callback(err);
+ }
+
+ if (!utils.isArray(results)) {
+ return callback(errors.InvalidResponse(results));
+ }
+
+ callback(err, results);
+ });
+};
+
+/**
* Should be used to set provider of request manager
*
* @method setProvider
@@ -3427,7 +3626,7 @@ RequestManager.prototype.stopPolling = function (pollId) {
*/
RequestManager.prototype.reset = function () {
this.polls.forEach(function (poll) {
- poll.uninstall(poll.id);
+ poll.uninstall(poll.id);
});
this.polls = [];
@@ -3465,7 +3664,7 @@ RequestManager.prototype.poll = function () {
if (error) {
return;
}
-
+
if (!utils.isArray(results)) {
throw errors.InvalidResponse(results);
}
@@ -3490,7 +3689,7 @@ RequestManager.prototype.poll = function () {
module.exports = RequestManager;
-},{"../utils/config":7,"../utils/utils":8,"./errors":13,"./jsonrpc":20}],26:[function(require,module,exports){
+},{"../utils/config":5,"../utils/utils":7,"./errors":13,"./jsonrpc":20}],26:[function(require,module,exports){
/*
This file is part of ethereum.js.
@@ -3517,8 +3716,8 @@ var Method = require('./method');
var formatters = require('./formatters');
var post = new Method({
- name: 'post',
- call: 'shh_post',
+ name: 'post',
+ call: 'shh_post',
params: 1,
inputFormatter: [formatters.inputPostFormatter]
});
@@ -3588,7 +3787,20 @@ var Method = require('./method');
/// @returns an array of objects describing web3.eth.filter api methods
var eth = function () {
var newFilterCall = function (args) {
- return typeof args[0] === 'string' ? 'eth_newBlockFilter' : 'eth_newFilter';
+ var type = args[0];
+
+ switch(type) {
+ case 'latest':
+ args.pop();
+ this.params = 0;
+ return 'eth_newBlockFilter';
+ case 'pending':
+ args.pop();
+ this.params = 0;
+ return 'eth_newPendingTransactionFilter';
+ default:
+ return 'eth_newFilter';
+ }
};
var newFilter = new Method({
@@ -3665,7 +3877,1382 @@ module.exports = {
},{"./method":21}],28:[function(require,module,exports){
-},{}],"bignumber.js":[function(require,module,exports){
+},{}],29:[function(require,module,exports){
+;(function (root, factory) {
+ if (typeof exports === "object") {
+ // CommonJS
+ module.exports = exports = factory();
+ }
+ else if (typeof define === "function" && define.amd) {
+ // AMD
+ define([], factory);
+ }
+ else {
+ // Global (browser)
+ root.CryptoJS = factory();
+ }
+}(this, function () {
+
+ /**
+ * CryptoJS core components.
+ */
+ var CryptoJS = CryptoJS || (function (Math, undefined) {
+ /**
+ * CryptoJS namespace.
+ */
+ var C = {};
+
+ /**
+ * Library namespace.
+ */
+ var C_lib = C.lib = {};
+
+ /**
+ * Base object for prototypal inheritance.
+ */
+ var Base = C_lib.Base = (function () {
+ function F() {}
+
+ return {
+ /**
+ * Creates a new object that inherits from this object.
+ *
+ * @param {Object} overrides Properties to copy into the new object.
+ *
+ * @return {Object} The new object.
+ *
+ * @static
+ *
+ * @example
+ *
+ * var MyType = CryptoJS.lib.Base.extend({
+ * field: 'value',
+ *
+ * method: function () {
+ * }
+ * });
+ */
+ extend: function (overrides) {
+ // Spawn
+ F.prototype = this;
+ var subtype = new F();
+
+ // Augment
+ if (overrides) {
+ subtype.mixIn(overrides);
+ }
+
+ // Create default initializer
+ if (!subtype.hasOwnProperty('init')) {
+ subtype.init = function () {
+ subtype.$super.init.apply(this, arguments);
+ };
+ }
+
+ // Initializer's prototype is the subtype object
+ subtype.init.prototype = subtype;
+
+ // Reference supertype
+ subtype.$super = this;
+
+ return subtype;
+ },
+
+ /**
+ * Extends this object and runs the init method.
+ * Arguments to create() will be passed to init().
+ *
+ * @return {Object} The new object.
+ *
+ * @static
+ *
+ * @example
+ *
+ * var instance = MyType.create();
+ */
+ create: function () {
+ var instance = this.extend();
+ instance.init.apply(instance, arguments);
+
+ return instance;
+ },
+
+ /**
+ * Initializes a newly created object.
+ * Override this method to add some logic when your objects are created.
+ *
+ * @example
+ *
+ * var MyType = CryptoJS.lib.Base.extend({
+ * init: function () {
+ * // ...
+ * }
+ * });
+ */
+ init: function () {
+ },
+
+ /**
+ * Copies properties into this object.
+ *
+ * @param {Object} properties The properties to mix in.
+ *
+ * @example
+ *
+ * MyType.mixIn({
+ * field: 'value'
+ * });
+ */
+ mixIn: function (properties) {
+ for (var propertyName in properties) {
+ if (properties.hasOwnProperty(propertyName)) {
+ this[propertyName] = properties[propertyName];
+ }
+ }
+
+ // IE won't copy toString using the loop above
+ if (properties.hasOwnProperty('toString')) {
+ this.toString = properties.toString;
+ }
+ },
+
+ /**
+ * Creates a copy of this object.
+ *
+ * @return {Object} The clone.
+ *
+ * @example
+ *
+ * var clone = instance.clone();
+ */
+ clone: function () {
+ return this.init.prototype.extend(this);
+ }
+ };
+ }());
+
+ /**
+ * An array of 32-bit words.
+ *
+ * @property {Array} words The array of 32-bit words.
+ * @property {number} sigBytes The number of significant bytes in this word array.
+ */
+ var WordArray = C_lib.WordArray = Base.extend({
+ /**
+ * Initializes a newly created word array.
+ *
+ * @param {Array} words (Optional) An array of 32-bit words.
+ * @param {number} sigBytes (Optional) The number of significant bytes in the words.
+ *
+ * @example
+ *
+ * var wordArray = CryptoJS.lib.WordArray.create();
+ * var wordArray = CryptoJS.lib.WordArray.create([0x00010203, 0x04050607]);
+ * var wordArray = CryptoJS.lib.WordArray.create([0x00010203, 0x04050607], 6);
+ */
+ init: function (words, sigBytes) {
+ words = this.words = words || [];
+
+ if (sigBytes != undefined) {
+ this.sigBytes = sigBytes;
+ } else {
+ this.sigBytes = words.length * 4;
+ }
+ },
+
+ /**
+ * Converts this word array to a string.
+ *
+ * @param {Encoder} encoder (Optional) The encoding strategy to use. Default: CryptoJS.enc.Hex
+ *
+ * @return {string} The stringified word array.
+ *
+ * @example
+ *
+ * var string = wordArray + '';
+ * var string = wordArray.toString();
+ * var string = wordArray.toString(CryptoJS.enc.Utf8);
+ */
+ toString: function (encoder) {
+ return (encoder || Hex).stringify(this);
+ },
+
+ /**
+ * Concatenates a word array to this word array.
+ *
+ * @param {WordArray} wordArray The word array to append.
+ *
+ * @return {WordArray} This word array.
+ *
+ * @example
+ *
+ * wordArray1.concat(wordArray2);
+ */
+ concat: function (wordArray) {
+ // Shortcuts
+ var thisWords = this.words;
+ var thatWords = wordArray.words;
+ var thisSigBytes = this.sigBytes;
+ var thatSigBytes = wordArray.sigBytes;
+
+ // Clamp excess bits
+ this.clamp();
+
+ // Concat
+ if (thisSigBytes % 4) {
+ // Copy one byte at a time
+ for (var i = 0; i < thatSigBytes; i++) {
+ var thatByte = (thatWords[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff;
+ thisWords[(thisSigBytes + i) >>> 2] |= thatByte << (24 - ((thisSigBytes + i) % 4) * 8);
+ }
+ } else if (thatWords.length > 0xffff) {
+ // Copy one word at a time
+ for (var i = 0; i < thatSigBytes; i += 4) {
+ thisWords[(thisSigBytes + i) >>> 2] = thatWords[i >>> 2];
+ }
+ } else {
+ // Copy all words at once
+ thisWords.push.apply(thisWords, thatWords);
+ }
+ this.sigBytes += thatSigBytes;
+
+ // Chainable
+ return this;
+ },
+
+ /**
+ * Removes insignificant bits.
+ *
+ * @example
+ *
+ * wordArray.clamp();
+ */
+ clamp: function () {
+ // Shortcuts
+ var words = this.words;
+ var sigBytes = this.sigBytes;
+
+ // Clamp
+ words[sigBytes >>> 2] &= 0xffffffff << (32 - (sigBytes % 4) * 8);
+ words.length = Math.ceil(sigBytes / 4);
+ },
+
+ /**
+ * Creates a copy of this word array.
+ *
+ * @return {WordArray} The clone.
+ *
+ * @example
+ *
+ * var clone = wordArray.clone();
+ */
+ clone: function () {
+ var clone = Base.clone.call(this);
+ clone.words = this.words.slice(0);
+
+ return clone;
+ },
+
+ /**
+ * Creates a word array filled with random bytes.
+ *
+ * @param {number} nBytes The number of random bytes to generate.
+ *
+ * @return {WordArray} The random word array.
+ *
+ * @static
+ *
+ * @example
+ *
+ * var wordArray = CryptoJS.lib.WordArray.random(16);
+ */
+ random: function (nBytes) {
+ var words = [];
+
+ var r = (function (m_w) {
+ var m_w = m_w;
+ var m_z = 0x3ade68b1;
+ var mask = 0xffffffff;
+
+ return function () {
+ m_z = (0x9069 * (m_z & 0xFFFF) + (m_z >> 0x10)) & mask;
+ m_w = (0x4650 * (m_w & 0xFFFF) + (m_w >> 0x10)) & mask;
+ var result = ((m_z << 0x10) + m_w) & mask;
+ result /= 0x100000000;
+ result += 0.5;
+ return result * (Math.random() > .5 ? 1 : -1);
+ }
+ });
+
+ for (var i = 0, rcache; i < nBytes; i += 4) {
+ var _r = r((rcache || Math.random()) * 0x100000000);
+
+ rcache = _r() * 0x3ade67b7;
+ words.push((_r() * 0x100000000) | 0);
+ }
+
+ return new WordArray.init(words, nBytes);
+ }
+ });
+
+ /**
+ * Encoder namespace.
+ */
+ var C_enc = C.enc = {};
+
+ /**
+ * Hex encoding strategy.
+ */
+ var Hex = C_enc.Hex = {
+ /**
+ * Converts a word array to a hex string.
+ *
+ * @param {WordArray} wordArray The word array.
+ *
+ * @return {string} The hex string.
+ *
+ * @static
+ *
+ * @example
+ *
+ * var hexString = CryptoJS.enc.Hex.stringify(wordArray);
+ */
+ stringify: function (wordArray) {
+ // Shortcuts
+ var words = wordArray.words;
+ var sigBytes = wordArray.sigBytes;
+
+ // Convert
+ var hexChars = [];
+ for (var i = 0; i < sigBytes; i++) {
+ var bite = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff;
+ hexChars.push((bite >>> 4).toString(16));
+ hexChars.push((bite & 0x0f).toString(16));
+ }
+
+ return hexChars.join('');
+ },
+
+ /**
+ * Converts a hex string to a word array.
+ *
+ * @param {string} hexStr The hex string.
+ *
+ * @return {WordArray} The word array.
+ *
+ * @static
+ *
+ * @example
+ *
+ * var wordArray = CryptoJS.enc.Hex.parse(hexString);
+ */
+ parse: function (hexStr) {
+ // Shortcut
+ var hexStrLength = hexStr.length;
+
+ // Convert
+ var words = [];
+ for (var i = 0; i < hexStrLength; i += 2) {
+ words[i >>> 3] |= parseInt(hexStr.substr(i, 2), 16) << (24 - (i % 8) * 4);
+ }
+
+ return new WordArray.init(words, hexStrLength / 2);
+ }
+ };
+
+ /**
+ * Latin1 encoding strategy.
+ */
+ var Latin1 = C_enc.Latin1 = {
+ /**
+ * Converts a word array to a Latin1 string.
+ *
+ * @param {WordArray} wordArray The word array.
+ *
+ * @return {string} The Latin1 string.
+ *
+ * @static
+ *
+ * @example
+ *
+ * var latin1String = CryptoJS.enc.Latin1.stringify(wordArray);
+ */
+ stringify: function (wordArray) {
+ // Shortcuts
+ var words = wordArray.words;
+ var sigBytes = wordArray.sigBytes;
+
+ // Convert
+ var latin1Chars = [];
+ for (var i = 0; i < sigBytes; i++) {
+ var bite = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff;
+ latin1Chars.push(String.fromCharCode(bite));
+ }
+
+ return latin1Chars.join('');
+ },
+
+ /**
+ * Converts a Latin1 string to a word array.
+ *
+ * @param {string} latin1Str The Latin1 string.
+ *
+ * @return {WordArray} The word array.
+ *
+ * @static
+ *
+ * @example
+ *
+ * var wordArray = CryptoJS.enc.Latin1.parse(latin1String);
+ */
+ parse: function (latin1Str) {
+ // Shortcut
+ var latin1StrLength = latin1Str.length;
+
+ // Convert
+ var words = [];
+ for (var i = 0; i < latin1StrLength; i++) {
+ words[i >>> 2] |= (latin1Str.charCodeAt(i) & 0xff) << (24 - (i % 4) * 8);
+ }
+
+ return new WordArray.init(words, latin1StrLength);
+ }
+ };
+
+ /**
+ * UTF-8 encoding strategy.
+ */
+ var Utf8 = C_enc.Utf8 = {
+ /**
+ * Converts a word array to a UTF-8 string.
+ *
+ * @param {WordArray} wordArray The word array.
+ *
+ * @return {string} The UTF-8 string.
+ *
+ * @static
+ *
+ * @example
+ *
+ * var utf8String = CryptoJS.enc.Utf8.stringify(wordArray);
+ */
+ stringify: function (wordArray) {
+ try {
+ return decodeURIComponent(escape(Latin1.stringify(wordArray)));
+ } catch (e) {
+ throw new Error('Malformed UTF-8 data');
+ }
+ },
+
+ /**
+ * Converts a UTF-8 string to a word array.
+ *
+ * @param {string} utf8Str The UTF-8 string.
+ *
+ * @return {WordArray} The word array.
+ *
+ * @static
+ *
+ * @example
+ *
+ * var wordArray = CryptoJS.enc.Utf8.parse(utf8String);
+ */
+ parse: function (utf8Str) {
+ return Latin1.parse(unescape(encodeURIComponent(utf8Str)));
+ }
+ };
+
+ /**
+ * Abstract buffered block algorithm template.
+ *
+ * The property blockSize must be implemented in a concrete subtype.
+ *
+ * @property {number} _minBufferSize The number of blocks that should be kept unprocessed in the buffer. Default: 0
+ */
+ var BufferedBlockAlgorithm = C_lib.BufferedBlockAlgorithm = Base.extend({
+ /**
+ * Resets this block algorithm's data buffer to its initial state.
+ *
+ * @example
+ *
+ * bufferedBlockAlgorithm.reset();
+ */
+ reset: function () {
+ // Initial values
+ this._data = new WordArray.init();
+ this._nDataBytes = 0;
+ },
+
+ /**
+ * Adds new data to this block algorithm's buffer.
+ *
+ * @param {WordArray|string} data The data to append. Strings are converted to a WordArray using UTF-8.
+ *
+ * @example
+ *
+ * bufferedBlockAlgorithm._append('data');
+ * bufferedBlockAlgorithm._append(wordArray);
+ */
+ _append: function (data) {
+ // Convert string to WordArray, else assume WordArray already
+ if (typeof data == 'string') {
+ data = Utf8.parse(data);
+ }
+
+ // Append
+ this._data.concat(data);
+ this._nDataBytes += data.sigBytes;
+ },
+
+ /**
+ * Processes available data blocks.
+ *
+ * This method invokes _doProcessBlock(offset), which must be implemented by a concrete subtype.
+ *
+ * @param {boolean} doFlush Whether all blocks and partial blocks should be processed.
+ *
+ * @return {WordArray} The processed data.
+ *
+ * @example
+ *
+ * var processedData = bufferedBlockAlgorithm._process();
+ * var processedData = bufferedBlockAlgorithm._process(!!'flush');
+ */
+ _process: function (doFlush) {
+ // Shortcuts
+ var data = this._data;
+ var dataWords = data.words;
+ var dataSigBytes = data.sigBytes;
+ var blockSize = this.blockSize;
+ var blockSizeBytes = blockSize * 4;
+
+ // Count blocks ready
+ var nBlocksReady = dataSigBytes / blockSizeBytes;
+ if (doFlush) {
+ // Round up to include partial blocks
+ nBlocksReady = Math.ceil(nBlocksReady);
+ } else {
+ // Round down to include only full blocks,
+ // less the number of blocks that must remain in the buffer
+ nBlocksReady = Math.max((nBlocksReady | 0) - this._minBufferSize, 0);
+ }
+
+ // Count words ready
+ var nWordsReady = nBlocksReady * blockSize;
+
+ // Count bytes ready
+ var nBytesReady = Math.min(nWordsReady * 4, dataSigBytes);
+
+ // Process blocks
+ if (nWordsReady) {
+ for (var offset = 0; offset < nWordsReady; offset += blockSize) {
+ // Perform concrete-algorithm logic
+ this._doProcessBlock(dataWords, offset);
+ }
+
+ // Remove processed words
+ var processedWords = dataWords.splice(0, nWordsReady);
+ data.sigBytes -= nBytesReady;
+ }
+
+ // Return processed words
+ return new WordArray.init(processedWords, nBytesReady);
+ },
+
+ /**
+ * Creates a copy of this object.
+ *
+ * @return {Object} The clone.
+ *
+ * @example
+ *
+ * var clone = bufferedBlockAlgorithm.clone();
+ */
+ clone: function () {
+ var clone = Base.clone.call(this);
+ clone._data = this._data.clone();
+
+ return clone;
+ },
+
+ _minBufferSize: 0
+ });
+
+ /**
+ * Abstract hasher template.
+ *
+ * @property {number} blockSize The number of 32-bit words this hasher operates on. Default: 16 (512 bits)
+ */
+ var Hasher = C_lib.Hasher = BufferedBlockAlgorithm.extend({
+ /**
+ * Configuration options.
+ */
+ cfg: Base.extend(),
+
+ /**
+ * Initializes a newly created hasher.
+ *
+ * @param {Object} cfg (Optional) The configuration options to use for this hash computation.
+ *
+ * @example
+ *
+ * var hasher = CryptoJS.algo.SHA256.create();
+ */
+ init: function (cfg) {
+ // Apply config defaults
+ this.cfg = this.cfg.extend(cfg);
+
+ // Set initial values
+ this.reset();
+ },
+
+ /**
+ * Resets this hasher to its initial state.
+ *
+ * @example
+ *
+ * hasher.reset();
+ */
+ reset: function () {
+ // Reset data buffer
+ BufferedBlockAlgorithm.reset.call(this);
+
+ // Perform concrete-hasher logic
+ this._doReset();
+ },
+
+ /**
+ * Updates this hasher with a message.
+ *
+ * @param {WordArray|string} messageUpdate The message to append.
+ *
+ * @return {Hasher} This hasher.
+ *
+ * @example
+ *
+ * hasher.update('message');
+ * hasher.update(wordArray);
+ */
+ update: function (messageUpdate) {
+ // Append
+ this._append(messageUpdate);
+
+ // Update the hash
+ this._process();
+
+ // Chainable
+ return this;
+ },
+
+ /**
+ * Finalizes the hash computation.
+ * Note that the finalize operation is effectively a destructive, read-once operation.
+ *
+ * @param {WordArray|string} messageUpdate (Optional) A final message update.
+ *
+ * @return {WordArray} The hash.
+ *
+ * @example
+ *
+ * var hash = hasher.finalize();
+ * var hash = hasher.finalize('message');
+ * var hash = hasher.finalize(wordArray);
+ */
+ finalize: function (messageUpdate) {
+ // Final message update
+ if (messageUpdate) {
+ this._append(messageUpdate);
+ }
+
+ // Perform concrete-hasher logic
+ var hash = this._doFinalize();
+
+ return hash;
+ },
+
+ blockSize: 512/32,
+
+ /**
+ * Creates a shortcut function to a hasher's object interface.
+ *
+ * @param {Hasher} hasher The hasher to create a helper for.
+ *
+ * @return {Function} The shortcut function.
+ *
+ * @static
+ *
+ * @example
+ *
+ * var SHA256 = CryptoJS.lib.Hasher._createHelper(CryptoJS.algo.SHA256);
+ */
+ _createHelper: function (hasher) {
+ return function (message, cfg) {
+ return new hasher.init(cfg).finalize(message);
+ };
+ },
+
+ /**
+ * Creates a shortcut function to the HMAC's object interface.
+ *
+ * @param {Hasher} hasher The hasher to use in this HMAC helper.
+ *
+ * @return {Function} The shortcut function.
+ *
+ * @static
+ *
+ * @example
+ *
+ * var HmacSHA256 = CryptoJS.lib.Hasher._createHmacHelper(CryptoJS.algo.SHA256);
+ */
+ _createHmacHelper: function (hasher) {
+ return function (message, key) {
+ return new C_algo.HMAC.init(hasher, key).finalize(message);
+ };
+ }
+ });
+
+ /**
+ * Algorithm namespace.
+ */
+ var C_algo = C.algo = {};
+
+ return C;
+ }(Math));
+
+
+ return CryptoJS;
+
+}));
+},{}],30:[function(require,module,exports){
+;(function (root, factory, undef) {
+ if (typeof exports === "object") {
+ // CommonJS
+ module.exports = exports = factory(require("./core"), require("./x64-core"));
+ }
+ else if (typeof define === "function" && define.amd) {
+ // AMD
+ define(["./core", "./x64-core"], factory);
+ }
+ else {
+ // Global (browser)
+ factory(root.CryptoJS);
+ }
+}(this, function (CryptoJS) {
+
+ (function (Math) {
+ // Shortcuts
+ var C = CryptoJS;
+ var C_lib = C.lib;
+ var WordArray = C_lib.WordArray;
+ var Hasher = C_lib.Hasher;
+ var C_x64 = C.x64;
+ var X64Word = C_x64.Word;
+ var C_algo = C.algo;
+
+ // Constants tables
+ var RHO_OFFSETS = [];
+ var PI_INDEXES = [];
+ var ROUND_CONSTANTS = [];
+
+ // Compute Constants
+ (function () {
+ // Compute rho offset constants
+ var x = 1, y = 0;
+ for (var t = 0; t < 24; t++) {
+ RHO_OFFSETS[x + 5 * y] = ((t + 1) * (t + 2) / 2) % 64;
+
+ var newX = y % 5;
+ var newY = (2 * x + 3 * y) % 5;
+ x = newX;
+ y = newY;
+ }
+
+ // Compute pi index constants
+ for (var x = 0; x < 5; x++) {
+ for (var y = 0; y < 5; y++) {
+ PI_INDEXES[x + 5 * y] = y + ((2 * x + 3 * y) % 5) * 5;
+ }
+ }
+
+ // Compute round constants
+ var LFSR = 0x01;
+ for (var i = 0; i < 24; i++) {
+ var roundConstantMsw = 0;
+ var roundConstantLsw = 0;
+
+ for (var j = 0; j < 7; j++) {
+ if (LFSR & 0x01) {
+ var bitPosition = (1 << j) - 1;
+ if (bitPosition < 32) {
+ roundConstantLsw ^= 1 << bitPosition;
+ } else /* if (bitPosition >= 32) */ {
+ roundConstantMsw ^= 1 << (bitPosition - 32);
+ }
+ }
+
+ // Compute next LFSR
+ if (LFSR & 0x80) {
+ // Primitive polynomial over GF(2): x^8 + x^6 + x^5 + x^4 + 1
+ LFSR = (LFSR << 1) ^ 0x71;
+ } else {
+ LFSR <<= 1;
+ }
+ }
+
+ ROUND_CONSTANTS[i] = X64Word.create(roundConstantMsw, roundConstantLsw);
+ }
+ }());
+
+ // Reusable objects for temporary values
+ var T = [];
+ (function () {
+ for (var i = 0; i < 25; i++) {
+ T[i] = X64Word.create();
+ }
+ }());
+
+ /**
+ * SHA-3 hash algorithm.
+ */
+ var SHA3 = C_algo.SHA3 = Hasher.extend({
+ /**
+ * Configuration options.
+ *
+ * @property {number} outputLength
+ * The desired number of bits in the output hash.
+ * Only values permitted are: 224, 256, 384, 512.
+ * Default: 512
+ */
+ cfg: Hasher.cfg.extend({
+ outputLength: 512
+ }),
+
+ _doReset: function () {
+ var state = this._state = []
+ for (var i = 0; i < 25; i++) {
+ state[i] = new X64Word.init();
+ }
+
+ this.blockSize = (1600 - 2 * this.cfg.outputLength) / 32;
+ },
+
+ _doProcessBlock: function (M, offset) {
+ // Shortcuts
+ var state = this._state;
+ var nBlockSizeLanes = this.blockSize / 2;
+
+ // Absorb
+ for (var i = 0; i < nBlockSizeLanes; i++) {
+ // Shortcuts
+ var M2i = M[offset + 2 * i];
+ var M2i1 = M[offset + 2 * i + 1];
+
+ // Swap endian
+ M2i = (
+ (((M2i << 8) | (M2i >>> 24)) & 0x00ff00ff) |
+ (((M2i << 24) | (M2i >>> 8)) & 0xff00ff00)
+ );
+ M2i1 = (
+ (((M2i1 << 8) | (M2i1 >>> 24)) & 0x00ff00ff) |
+ (((M2i1 << 24) | (M2i1 >>> 8)) & 0xff00ff00)
+ );
+
+ // Absorb message into state
+ var lane = state[i];
+ lane.high ^= M2i1;
+ lane.low ^= M2i;
+ }
+
+ // Rounds
+ for (var round = 0; round < 24; round++) {
+ // Theta
+ for (var x = 0; x < 5; x++) {
+ // Mix column lanes
+ var tMsw = 0, tLsw = 0;
+ for (var y = 0; y < 5; y++) {
+ var lane = state[x + 5 * y];
+ tMsw ^= lane.high;
+ tLsw ^= lane.low;
+ }
+
+ // Temporary values
+ var Tx = T[x];
+ Tx.high = tMsw;
+ Tx.low = tLsw;
+ }
+ for (var x = 0; x < 5; x++) {
+ // Shortcuts
+ var Tx4 = T[(x + 4) % 5];
+ var Tx1 = T[(x + 1) % 5];
+ var Tx1Msw = Tx1.high;
+ var Tx1Lsw = Tx1.low;
+
+ // Mix surrounding columns
+ var tMsw = Tx4.high ^ ((Tx1Msw << 1) | (Tx1Lsw >>> 31));
+ var tLsw = Tx4.low ^ ((Tx1Lsw << 1) | (Tx1Msw >>> 31));
+ for (var y = 0; y < 5; y++) {
+ var lane = state[x + 5 * y];
+ lane.high ^= tMsw;
+ lane.low ^= tLsw;
+ }
+ }
+
+ // Rho Pi
+ for (var laneIndex = 1; laneIndex < 25; laneIndex++) {
+ // Shortcuts
+ var lane = state[laneIndex];
+ var laneMsw = lane.high;
+ var laneLsw = lane.low;
+ var rhoOffset = RHO_OFFSETS[laneIndex];
+
+ // Rotate lanes
+ if (rhoOffset < 32) {
+ var tMsw = (laneMsw << rhoOffset) | (laneLsw >>> (32 - rhoOffset));
+ var tLsw = (laneLsw << rhoOffset) | (laneMsw >>> (32 - rhoOffset));
+ } else /* if (rhoOffset >= 32) */ {
+ var tMsw = (laneLsw << (rhoOffset - 32)) | (laneMsw >>> (64 - rhoOffset));
+ var tLsw = (laneMsw << (rhoOffset - 32)) | (laneLsw >>> (64 - rhoOffset));
+ }
+
+ // Transpose lanes
+ var TPiLane = T[PI_INDEXES[laneIndex]];
+ TPiLane.high = tMsw;
+ TPiLane.low = tLsw;
+ }
+
+ // Rho pi at x = y = 0
+ var T0 = T[0];
+ var state0 = state[0];
+ T0.high = state0.high;
+ T0.low = state0.low;
+
+ // Chi
+ for (var x = 0; x < 5; x++) {
+ for (var y = 0; y < 5; y++) {
+ // Shortcuts
+ var laneIndex = x + 5 * y;
+ var lane = state[laneIndex];
+ var TLane = T[laneIndex];
+ var Tx1Lane = T[((x + 1) % 5) + 5 * y];
+ var Tx2Lane = T[((x + 2) % 5) + 5 * y];
+
+ // Mix rows
+ lane.high = TLane.high ^ (~Tx1Lane.high & Tx2Lane.high);
+ lane.low = TLane.low ^ (~Tx1Lane.low & Tx2Lane.low);
+ }
+ }
+
+ // Iota
+ var lane = state[0];
+ var roundConstant = ROUND_CONSTANTS[round];
+ lane.high ^= roundConstant.high;
+ lane.low ^= roundConstant.low;;
+ }
+ },
+
+ _doFinalize: function () {
+ // Shortcuts
+ var data = this._data;
+ var dataWords = data.words;
+ var nBitsTotal = this._nDataBytes * 8;
+ var nBitsLeft = data.sigBytes * 8;
+ var blockSizeBits = this.blockSize * 32;
+
+ // Add padding
+ dataWords[nBitsLeft >>> 5] |= 0x1 << (24 - nBitsLeft % 32);
+ dataWords[((Math.ceil((nBitsLeft + 1) / blockSizeBits) * blockSizeBits) >>> 5) - 1] |= 0x80;
+ data.sigBytes = dataWords.length * 4;
+
+ // Hash final blocks
+ this._process();
+
+ // Shortcuts
+ var state = this._state;
+ var outputLengthBytes = this.cfg.outputLength / 8;
+ var outputLengthLanes = outputLengthBytes / 8;
+
+ // Squeeze
+ var hashWords = [];
+ for (var i = 0; i < outputLengthLanes; i++) {
+ // Shortcuts
+ var lane = state[i];
+ var laneMsw = lane.high;
+ var laneLsw = lane.low;
+
+ // Swap endian
+ laneMsw = (
+ (((laneMsw << 8) | (laneMsw >>> 24)) & 0x00ff00ff) |
+ (((laneMsw << 24) | (laneMsw >>> 8)) & 0xff00ff00)
+ );
+ laneLsw = (
+ (((laneLsw << 8) | (laneLsw >>> 24)) & 0x00ff00ff) |
+ (((laneLsw << 24) | (laneLsw >>> 8)) & 0xff00ff00)
+ );
+
+ // Squeeze state to retrieve hash
+ hashWords.push(laneLsw);
+ hashWords.push(laneMsw);
+ }
+
+ // Return final computed hash
+ return new WordArray.init(hashWords, outputLengthBytes);
+ },
+
+ clone: function () {
+ var clone = Hasher.clone.call(this);
+
+ var state = clone._state = this._state.slice(0);
+ for (var i = 0; i < 25; i++) {
+ state[i] = state[i].clone();
+ }
+
+ return clone;
+ }
+ });
+
+ /**
+ * Shortcut function to the hasher's object interface.
+ *
+ * @param {WordArray|string} message The message to hash.
+ *
+ * @return {WordArray} The hash.
+ *
+ * @static
+ *
+ * @example
+ *
+ * var hash = CryptoJS.SHA3('message');
+ * var hash = CryptoJS.SHA3(wordArray);
+ */
+ C.SHA3 = Hasher._createHelper(SHA3);
+
+ /**
+ * Shortcut function to the HMAC's object interface.
+ *
+ * @param {WordArray|string} message The message to hash.
+ * @param {WordArray|string} key The secret key.
+ *
+ * @return {WordArray} The HMAC.
+ *
+ * @static
+ *
+ * @example
+ *
+ * var hmac = CryptoJS.HmacSHA3(message, key);
+ */
+ C.HmacSHA3 = Hasher._createHmacHelper(SHA3);
+ }(Math));
+
+
+ return CryptoJS.SHA3;
+
+}));
+},{"./core":29,"./x64-core":31}],31:[function(require,module,exports){
+;(function (root, factory) {
+ if (typeof exports === "object") {
+ // CommonJS
+ module.exports = exports = factory(require("./core"));
+ }
+ else if (typeof define === "function" && define.amd) {
+ // AMD
+ define(["./core"], factory);
+ }
+ else {
+ // Global (browser)
+ factory(root.CryptoJS);
+ }
+}(this, function (CryptoJS) {
+
+ (function (undefined) {
+ // Shortcuts
+ var C = CryptoJS;
+ var C_lib = C.lib;
+ var Base = C_lib.Base;
+ var X32WordArray = C_lib.WordArray;
+
+ /**
+ * x64 namespace.
+ */
+ var C_x64 = C.x64 = {};
+
+ /**
+ * A 64-bit word.
+ */
+ var X64Word = C_x64.Word = Base.extend({
+ /**
+ * Initializes a newly created 64-bit word.
+ *
+ * @param {number} high The high 32 bits.
+ * @param {number} low The low 32 bits.
+ *
+ * @example
+ *
+ * var x64Word = CryptoJS.x64.Word.create(0x00010203, 0x04050607);
+ */
+ init: function (high, low) {
+ this.high = high;
+ this.low = low;
+ }
+
+ /**
+ * Bitwise NOTs this word.
+ *
+ * @return {X64Word} A new x64-Word object after negating.
+ *
+ * @example
+ *
+ * var negated = x64Word.not();
+ */
+ // not: function () {
+ // var high = ~this.high;
+ // var low = ~this.low;
+
+ // return X64Word.create(high, low);
+ // },
+
+ /**
+ * Bitwise ANDs this word with the passed word.
+ *
+ * @param {X64Word} word The x64-Word to AND with this word.
+ *
+ * @return {X64Word} A new x64-Word object after ANDing.
+ *
+ * @example
+ *
+ * var anded = x64Word.and(anotherX64Word);
+ */
+ // and: function (word) {
+ // var high = this.high & word.high;
+ // var low = this.low & word.low;
+
+ // return X64Word.create(high, low);
+ // },
+
+ /**
+ * Bitwise ORs this word with the passed word.
+ *
+ * @param {X64Word} word The x64-Word to OR with this word.
+ *
+ * @return {X64Word} A new x64-Word object after ORing.
+ *
+ * @example
+ *
+ * var ored = x64Word.or(anotherX64Word);
+ */
+ // or: function (word) {
+ // var high = this.high | word.high;
+ // var low = this.low | word.low;
+
+ // return X64Word.create(high, low);
+ // },
+
+ /**
+ * Bitwise XORs this word with the passed word.
+ *
+ * @param {X64Word} word The x64-Word to XOR with this word.
+ *
+ * @return {X64Word} A new x64-Word object after XORing.
+ *
+ * @example
+ *
+ * var xored = x64Word.xor(anotherX64Word);
+ */
+ // xor: function (word) {
+ // var high = this.high ^ word.high;
+ // var low = this.low ^ word.low;
+
+ // return X64Word.create(high, low);
+ // },
+
+ /**
+ * Shifts this word n bits to the left.
+ *
+ * @param {number} n The number of bits to shift.
+ *
+ * @return {X64Word} A new x64-Word object after shifting.
+ *
+ * @example
+ *
+ * var shifted = x64Word.shiftL(25);
+ */
+ // shiftL: function (n) {
+ // if (n < 32) {
+ // var high = (this.high << n) | (this.low >>> (32 - n));
+ // var low = this.low << n;
+ // } else {
+ // var high = this.low << (n - 32);
+ // var low = 0;
+ // }
+
+ // return X64Word.create(high, low);
+ // },
+
+ /**
+ * Shifts this word n bits to the right.
+ *
+ * @param {number} n The number of bits to shift.
+ *
+ * @return {X64Word} A new x64-Word object after shifting.
+ *
+ * @example
+ *
+ * var shifted = x64Word.shiftR(7);
+ */
+ // shiftR: function (n) {
+ // if (n < 32) {
+ // var low = (this.low >>> n) | (this.high << (32 - n));
+ // var high = this.high >>> n;
+ // } else {
+ // var low = this.high >>> (n - 32);
+ // var high = 0;
+ // }
+
+ // return X64Word.create(high, low);
+ // },
+
+ /**
+ * Rotates this word n bits to the left.
+ *
+ * @param {number} n The number of bits to rotate.
+ *
+ * @return {X64Word} A new x64-Word object after rotating.
+ *
+ * @example
+ *
+ * var rotated = x64Word.rotL(25);
+ */
+ // rotL: function (n) {
+ // return this.shiftL(n).or(this.shiftR(64 - n));
+ // },
+
+ /**
+ * Rotates this word n bits to the right.
+ *
+ * @param {number} n The number of bits to rotate.
+ *
+ * @return {X64Word} A new x64-Word object after rotating.
+ *
+ * @example
+ *
+ * var rotated = x64Word.rotR(7);
+ */
+ // rotR: function (n) {
+ // return this.shiftR(n).or(this.shiftL(64 - n));
+ // },
+
+ /**
+ * Adds this word with the passed word.
+ *
+ * @param {X64Word} word The x64-Word to add with this word.
+ *
+ * @return {X64Word} A new x64-Word object after adding.
+ *
+ * @example
+ *
+ * var added = x64Word.add(anotherX64Word);
+ */
+ // add: function (word) {
+ // var low = (this.low + word.low) | 0;
+ // var carry = (low >>> 0) < (this.low >>> 0) ? 1 : 0;
+ // var high = (this.high + word.high + carry) | 0;
+
+ // return X64Word.create(high, low);
+ // }
+ });
+
+ /**
+ * An array of 64-bit words.
+ *
+ * @property {Array} words The array of CryptoJS.x64.Word objects.
+ * @property {number} sigBytes The number of significant bytes in this word array.
+ */
+ var X64WordArray = C_x64.WordArray = Base.extend({
+ /**
+ * Initializes a newly created word array.
+ *
+ * @param {Array} words (Optional) An array of CryptoJS.x64.Word objects.
+ * @param {number} sigBytes (Optional) The number of significant bytes in the words.
+ *
+ * @example
+ *
+ * var wordArray = CryptoJS.x64.WordArray.create();
+ *
+ * var wordArray = CryptoJS.x64.WordArray.create([
+ * CryptoJS.x64.Word.create(0x00010203, 0x04050607),
+ * CryptoJS.x64.Word.create(0x18191a1b, 0x1c1d1e1f)
+ * ]);
+ *
+ * var wordArray = CryptoJS.x64.WordArray.create([
+ * CryptoJS.x64.Word.create(0x00010203, 0x04050607),
+ * CryptoJS.x64.Word.create(0x18191a1b, 0x1c1d1e1f)
+ * ], 10);
+ */
+ init: function (words, sigBytes) {
+ words = this.words = words || [];
+
+ if (sigBytes != undefined) {
+ this.sigBytes = sigBytes;
+ } else {
+ this.sigBytes = words.length * 8;
+ }
+ },
+
+ /**
+ * Converts this 64-bit word array to a 32-bit word array.
+ *
+ * @return {CryptoJS.lib.WordArray} This word array's data as a 32-bit word array.
+ *
+ * @example
+ *
+ * var x32WordArray = x64WordArray.toX32();
+ */
+ toX32: function () {
+ // Shortcuts
+ var x64Words = this.words;
+ var x64WordsLength = x64Words.length;
+
+ // Convert
+ var x32Words = [];
+ for (var i = 0; i < x64WordsLength; i++) {
+ var x64Word = x64Words[i];
+ x32Words.push(x64Word.high);
+ x32Words.push(x64Word.low);
+ }
+
+ return X32WordArray.create(x32Words, this.sigBytes);
+ },
+
+ /**
+ * Creates a copy of this word array.
+ *
+ * @return {X64WordArray} The clone.
+ *
+ * @example
+ *
+ * var clone = x64WordArray.clone();
+ */
+ clone: function () {
+ var clone = Base.clone.call(this);
+
+ // Clone "words" array
+ var words = clone.words = this.words.slice(0);
+
+ // Clone each X64Word object
+ var wordsLength = words.length;
+ for (var i = 0; i < wordsLength; i++) {
+ words[i] = words[i].clone();
+ }
+
+ return clone;
+ }
+ });
+ }());
+
+
+ return CryptoJS;
+
+}));
+},{"./core":29}],"bignumber.js":[function(require,module,exports){
'use strict';
module.exports = BigNumber; // jshint ignore:line
@@ -3676,7 +5263,6 @@ var web3 = require('./lib/web3');
web3.providers.HttpProvider = require('./lib/web3/httpprovider');
web3.providers.QtSyncProvider = require('./lib/web3/qtsync');
web3.eth.contract = require('./lib/web3/contract');
-web3.abi = require('./lib/solidity/abi');
// dont override global variable
if (typeof window !== 'undefined' && typeof window.web3 === 'undefined') {
@@ -3686,7 +5272,7 @@ if (typeof window !== 'undefined' && typeof window.web3 === 'undefined') {
module.exports = web3;
-},{"./lib/solidity/abi":1,"./lib/web3":10,"./lib/web3/contract":11,"./lib/web3/httpprovider":19,"./lib/web3/qtsync":24}]},{},["web3"])
+},{"./lib/web3":9,"./lib/web3/contract":11,"./lib/web3/httpprovider":19,"./lib/web3/qtsync":24}]},{},["web3"])
//# sourceMappingURL=web3-light.js.map
diff --git a/miner/worker.go b/miner/worker.go
index 5fa5d3777..5e4ff7510 100644
--- a/miner/worker.go
+++ b/miner/worker.go
@@ -270,6 +270,7 @@ func (self *worker) makeCurrent() {
}
block.Header().Extra = self.extra
+ // when 08 is processed ancestors contain 07 (quick block)
current := env(block, self.eth)
for _, ancestor := range self.chain.GetAncestors(block, 7) {
for _, uncle := range ancestor.Uncles() {
diff --git a/rpc/api.go b/rpc/api.go
index 0c1409d71..b6f6ac3f9 100644
--- a/rpc/api.go
+++ b/rpc/api.go
@@ -158,16 +158,16 @@ func (api *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) err
v := api.xethAtStateNum(args.BlockNumber).CodeAtBytes(args.Address)
*reply = newHexData(v)
- case "eth_sign":
- args := new(NewSigArgs)
- if err := json.Unmarshal(req.Params, &args); err != nil {
- return err
- }
- v, err := api.xeth().Sign(args.From, args.Data, false)
- if err != nil {
- return err
- }
- *reply = v
+ // case "eth_sign":
+ // args := new(NewSigArgs)
+ // if err := json.Unmarshal(req.Params, &args); err != nil {
+ // return err
+ // }
+ // v, err := api.xeth().Sign(args.From, args.Data, false)
+ // if err != nil {
+ // return err
+ // }
+ // *reply = v
case "eth_sendTransaction", "eth_transact":
args := new(NewTxArgs)
@@ -347,7 +347,7 @@ func (api *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) err
solc, _ := api.xeth().Solc()
if solc == nil {
- return NewNotImplementedError(req.Method)
+ return NewNotAvailableError(req.Method, "solc (solidity compiler) not found")
}
args := new(SourceArgs)
@@ -355,12 +355,11 @@ func (api *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) err
return err
}
- contract, err := solc.Compile(args.Source)
+ contracts, err := solc.Compile(args.Source)
if err != nil {
return err
}
- contract.Code = newHexData(contract.Code).String()
- *reply = contract
+ *reply = contracts
case "eth_newFilter":
args := new(BlockFilterArgs)
diff --git a/rpc/api_test.go b/rpc/api_test.go
index b49e27bd1..d1dcad266 100644
--- a/rpc/api_test.go
+++ b/rpc/api_test.go
@@ -2,14 +2,11 @@ package rpc
import (
"encoding/json"
- // "sync"
- "testing"
- // "time"
- // "fmt"
- "io/ioutil"
"strconv"
+ "testing"
"github.com/ethereum/go-ethereum/common/compiler"
+ "github.com/ethereum/go-ethereum/eth"
"github.com/ethereum/go-ethereum/xeth"
)
@@ -30,12 +27,15 @@ func TestWeb3Sha3(t *testing.T) {
}
}
+const solcVersion = "0.9.23"
+
func TestCompileSolidity(t *testing.T) {
- t.Skip()
solc, err := compiler.New("")
if solc == nil {
- t.Skip("no solidity compiler")
+ t.Skip("no solc found: skip")
+ } else if solc.Version() != solcVersion {
+ t.Logf("WARNING: solc different version found (%v, test written for %v, may need to update)", solc.Version(), solcVersion)
}
source := `contract test {\n` +
" /// @notice Will multiply `a` by 7." + `\n` +
@@ -46,16 +46,16 @@ func TestCompileSolidity(t *testing.T) {
jsonstr := `{"jsonrpc":"2.0","method":"eth_compileSolidity","params":["` + source + `"],"id":64}`
- //expCode := "605280600c6000396000f3006000357c010000000000000000000000000000000000000000000000000000000090048063c6888fa114602e57005b60376004356041565b8060005260206000f35b6000600782029050604d565b91905056"
+ expCode := "0x605880600c6000396000f3006000357c010000000000000000000000000000000000000000000000000000000090048063c6888fa114602e57005b603d6004803590602001506047565b8060005260206000f35b60006007820290506053565b91905056"
expAbiDefinition := `[{"constant":false,"inputs":[{"name":"a","type":"uint256"}],"name":"multiply","outputs":[{"name":"d","type":"uint256"}],"type":"function"}]`
expUserDoc := `{"methods":{"multiply(uint256)":{"notice":"Will multiply ` + "`a`" + ` by 7."}}}`
expDeveloperDoc := `{"methods":{}}`
- expCompilerVersion := `0.9.13`
+ expCompilerVersion := solc.Version()
expLanguage := "Solidity"
expLanguageVersion := "0"
expSource := source
- api := NewEthereumApi(&xeth.XEth{})
+ api := NewEthereumApi(xeth.NewTest(&eth.Ethereum{}, nil))
var req RpcRequest
json.Unmarshal([]byte(jsonstr), &req)
@@ -70,26 +70,34 @@ func TestCompileSolidity(t *testing.T) {
t.Errorf("expected no error, got %v", err)
}
- var contract = compiler.Contract{}
- err = json.Unmarshal(respjson, &contract)
+ var contracts = make(map[string]*compiler.Contract)
+ err = json.Unmarshal(respjson, &contracts)
if err != nil {
t.Errorf("expected no error, got %v", err)
}
- /*
- if contract.Code != expCode {
- t.Errorf("Expected %s got %s", expCode, contract.Code)
- }
- */
+ if len(contracts) != 1 {
+ t.Errorf("expected one contract, got %v", len(contracts))
+ }
+
+ contract := contracts["test"]
+
+ if contract.Code != expCode {
+ t.Errorf("Expected \n%s got \n%s", expCode, contract.Code)
+ }
+
if strconv.Quote(contract.Info.Source) != `"`+expSource+`"` {
t.Errorf("Expected \n'%s' got \n'%s'", expSource, strconv.Quote(contract.Info.Source))
}
+
if contract.Info.Language != expLanguage {
t.Errorf("Expected %s got %s", expLanguage, contract.Info.Language)
}
+
if contract.Info.LanguageVersion != expLanguageVersion {
t.Errorf("Expected %s got %s", expLanguageVersion, contract.Info.LanguageVersion)
}
+
if contract.Info.CompilerVersion != expCompilerVersion {
t.Errorf("Expected %s got %s", expCompilerVersion, contract.Info.CompilerVersion)
}
@@ -112,8 +120,6 @@ func TestCompileSolidity(t *testing.T) {
if string(abidef) != expAbiDefinition {
t.Errorf("Expected \n'%s' got \n'%s'", expAbiDefinition, string(abidef))
}
- ioutil.WriteFile("/tmp/abidef", []byte(string(abidef)), 0700)
- ioutil.WriteFile("/tmp/expabidef", []byte(expAbiDefinition), 0700)
if string(userdoc) != expUserDoc {
t.Errorf("Expected \n'%s' got \n'%s'", expUserDoc, string(userdoc))
diff --git a/rpc/args.go b/rpc/args.go
index 686872a59..27824f12c 100644
--- a/rpc/args.go
+++ b/rpc/args.go
@@ -166,45 +166,45 @@ type NewTxArgs struct {
BlockNumber int64
}
-type NewSigArgs struct {
- From string
- Data string
-}
+// type NewSigArgs struct {
+// From string
+// Data string
+// }
-func (args *NewSigArgs) UnmarshalJSON(b []byte) (err error) {
- var obj []json.RawMessage
- var ext struct {
- From string
- Data string
- }
+// func (args *NewSigArgs) UnmarshalJSON(b []byte) (err error) {
+// var obj []json.RawMessage
+// var ext struct {
+// From string
+// Data string
+// }
- // Decode byte slice to array of RawMessages
- if err := json.Unmarshal(b, &obj); err != nil {
- return NewDecodeParamError(err.Error())
- }
+// // Decode byte slice to array of RawMessages
+// if err := json.Unmarshal(b, &obj); err != nil {
+// return NewDecodeParamError(err.Error())
+// }
- // Check for sufficient params
- if len(obj) < 1 {
- return NewInsufficientParamsError(len(obj), 1)
- }
+// // Check for sufficient params
+// if len(obj) < 1 {
+// return NewInsufficientParamsError(len(obj), 1)
+// }
- // Decode 0th RawMessage to temporary struct
- if err := json.Unmarshal(obj[0], &ext); err != nil {
- return NewDecodeParamError(err.Error())
- }
+// // Decode 0th RawMessage to temporary struct
+// if err := json.Unmarshal(obj[0], &ext); err != nil {
+// return NewDecodeParamError(err.Error())
+// }
- if len(ext.From) == 0 {
- return NewValidationError("from", "is required")
- }
+// if len(ext.From) == 0 {
+// return NewValidationError("from", "is required")
+// }
- if len(ext.Data) == 0 {
- return NewValidationError("data", "is required")
- }
+// if len(ext.Data) == 0 {
+// return NewValidationError("data", "is required")
+// }
- args.From = ext.From
- args.Data = ext.Data
- return nil
-}
+// args.From = ext.From
+// args.Data = ext.Data
+// return nil
+// }
func (args *NewTxArgs) UnmarshalJSON(b []byte) (err error) {
var obj []json.RawMessage
diff --git a/xeth/xeth.go b/xeth/xeth.go
index 7de3e31be..4925fe635 100644
--- a/xeth/xeth.go
+++ b/xeth/xeth.go
@@ -66,12 +66,16 @@ type XEth struct {
// regmut sync.Mutex
// register map[string][]*interface{} // TODO improve return type
- solcPath string
- solc *compiler.Solidity
-
agent *miner.RemoteAgent
}
+func NewTest(eth *eth.Ethereum, frontend Frontend) *XEth {
+ return &XEth{
+ backend: eth,
+ frontend: frontend,
+ }
+}
+
// New creates an XEth that uses the given frontend.
// If a nil Frontend is provided, a default frontend which
// confirms all transactions will be used.
@@ -379,17 +383,12 @@ func (self *XEth) Accounts() []string {
// accessor for solidity compiler.
// memoized if available, retried on-demand if not
func (self *XEth) Solc() (*compiler.Solidity, error) {
- var err error
- if self.solc == nil {
- self.solc, err = compiler.New(self.solcPath)
- }
- return self.solc, err
+ return self.backend.Solc()
}
// set in js console via admin interface or wrapper from cli flags
func (self *XEth) SetSolc(solcPath string) (*compiler.Solidity, error) {
- self.solcPath = solcPath
- self.solc = nil
+ self.backend.SetSolc(solcPath)
return self.Solc()
}