EExcel 丞燕快速查詢2

EExcel 丞燕快速查詢2
EExcel 丞燕快速查詢2 https://sandk.ffbizs.com/

fb 中研院研究出快篩試劑

漂亮的諧音 https://www.youtube.com/channel/UCRSmPITY7izy2F1INKMEf2g
13 小時前

中研院研究出快篩試劑,
綠媒大肆吹捧,
817們高潮連連,
綠媒說根本是大陸搶了台灣的研究功勞,
結果人家那是2月的事,
如何搶台灣3月研發出來的成果功勞?
(原來中國有坐時光機穿越未來,
抄襲台灣研究成果的能力啊)

。。。

接著衛福部被抓包,
2月就核准進口大陸快篩試劑,
但衛福部辯解說進口的是抗體試劑,
中研院研發的是抗原試劑,
(既然兩者快篩試劑不同,
那白痴綠媒說大陸搶了台灣研究功勞,
這是什麼毛病?
反正只要政治正確,
造謠就沒問題是嘛!?)

。。。

那中研院的快篩試劑何時可量產?
中研院長回覆說:
『此一問題「難以回答」。
做試劑不能為了趕進度忽略靈敏性與準確度。
而快篩何時人體試驗、量產,
都必須與衛福部、廠商密切合作,
時間難以預估。
「即使今年用不上,
也必須為未來的疫情做準備。」』

。。。

所以817在高潮一個,
根本還無法真正問世的東西。
台灣現在就是腦殘當道啊!

[轉]Keep your promises when using Cloud Functions for Firebase!

https://firebase.googleblog.com/2017/06/keep-your-promises-when-using-cloud.html?fbclid=IwAR2FuvlU2CbwjV-I75q7-WIkJyLHRYT-R3cyleEUWF3Fsq42THMCwZN6by8


const ref_p1_state = root.child(`player_states/${game_state.p1uid}`)
const ref_p2_state = root.child(`player_states/${game_state.p2uid}`)
const pr_update_p1 = ref_p1_state.update(update_p1)
const pr_update_p2 = ref_p2_state.update(update_p2)

return Promise.all([pr_update_p1, pr_update_p2])


==========

https://stackoverflow.com/questions/55430079/promise-all-does-not-wait-for-firestore-query-to-loop

nodexjs expressjs ajv apidoc converter generator restclient curl postman

ajv schema to apidoc schema
https://github.com/willfarrell/apidoc-plugin-schema

required can't product doc.


converter
https://github.com/apidoc/apidoc#converter

to swagger
https://github.com/fsbahman/apidoc-swagger

postman collection to apidoc
https://github.com/bonzzy/docmaster

RestClient -> curl -> postman

promise.all error catch

https://stackoverflow.com/questions/30362733/handling-errors-in-promise-all



Promise.all(state.routes.map(function(route) {
  return route.handler.promiseHandler().catch(function(err) {
    return err;
  });
}))
.then(function(arrayOfValuesOrErrors) {
  // handling of my array containing values and/or errors. 
})
.catch(function(err) {
  console.log(err.message); // some coding error in handling happened
});


Alternately, if you have a case where you don't particularly care about the values of the resolved promises when there is one failure but you still want them to have run, you could do something like this which will resolve with the promises as normal when they all succeed and reject with the failed promises when any of them fail:



function promiseNoReallyAll (promises) {
  return new Promise(
    async (resolve, reject) => {
      const failedPromises = []

      const successfulPromises = await Promise.all(
        promises.map(
          promise => promise.catch(error => {
            failedPromises.push(error)
          })
        )
      )

      if (failedPromises.length) {
        reject(failedPromises)
      } else {
        resolve(successfulPromises)
      }
    }
  )
}

firestore import

使用 https://github.com/dalenguyen/firestore-backup-restore
base on https://github.com/dalenguyen/firestore-import-export

能處理timestamp

filestore2json json2filestore

https://gist.github.com/sturmenta/cbbe898227cb1eaca7f85d0191eaec7e#gistcomment-2837988

ok can use. good job.

timestamp have error.

pve Transparent Failover



Ray Tracy HA 只是高可用度,他沒有不停頓 (Non-stop) 等級的容錯(FT)能力,所以只能把死掉的 VM 重開機來復原,他做不到:接手死掉 VM 當時狀態,不停頓的執行下去....

市面上可穩定商轉的 FT 軟體最便宜也要上百萬起跳....且對硬體條件有諸多限制...

還有,測試 HA 盡量採用拔電源線的方式,而不是只拔網路線,否則在複雜網路環境中,復原後可能整個 Cluster 會發生 #叢集腦裂(雖然機率很小,你還是可以賭看看)....

而且原本初階 HA 就是設計成:用來對抗 Host 全機故障,而不是對抗只有網路故障;所以即便將網路隔離,若 Host 沒掛掉的話,復原的時候都會有風險.....

完整的 HA 流程,在啟動備用 VM 之前,Cluster 會先自動下 ipmi 或 BMC 指令給隔離的 Host 強制它完全關機之後,才啟動備用 VM, 就是為了避免發生上述風險....(這個動作稱為 fence)

這裡大部分玩 cluster 的人都不知道要去設定 ipmi/bmc 做 fence; 如果有設定 fence 的話, 就可以用拔網路線來做測試了, 因為拔掉之後, fence 會自動去把那台隔離的 host 關機, 就不會發生復原之後的腦裂問題.....(當然, 你不能去拔 fence 用的那條 ipmi 網路線...🤣🤣🤣)



Jason Cheng 如果經費不多想做 FT,可以參考台灣團隊開發的 Cuju 專案,基於 kvm 實作,去年底 Proxmox 社團使用者年會該團隊講者有來分享

https://github.com/Cuju-ft/Cuju

國小台語課不教台語,教什麼

https://youtu.be/2YlD3fsszT0?t=2436


孙杨

https://www.youtube.com/watch?v=ILICiagUIQ0

http://lanxiongsports.com/posts/view/id/17753.html

228 武之璋 有書

https://www.youtube.com/watch?v=gzpCMIv3zVc

我们和世界各地的朋友,聊了聊他们那里的疫情|故事FM

https://mp.weixin.qq.com/s/PxFYCZVELj8q0ybkhxoGhQ

造一个病毒有多难|大象公会

https://mp.weixin.qq.com/s/YX98XfO6Rb4EaBT8vRp8YA

拿H1N1來對比武漢肺炎

拿H1N1來對比武漢肺炎

中間一些部份內容,讓人理解到為什麼日韓和美國都不是很在意

https://www.youtube.com/watch?v=rJiKxV4rTCQ


https://www.youtube.com/watch?v=K2TYIV6osR8



https://www.youtube.com/watch?v=K2TYIV6osR8


https://youtu.be/UBYPkjs9ve4?t=315
https://youtu.be/UBYPkjs9ve4?t=511

https://youtu.be/0RI5JsfuZKE?t=22

https://www.youtube.com/watch?v=bPvuqvc5C1M 纽约首例新冠患者未在医院治疗,纽约州长:80%都能自愈 没必要去医院
https://www.youtube.com/watch?v=AiCghCxro8o
https://www.guancha.cn/internation/2020_03_03_539596.shtml

螢幕色彩偏離值

PS42對於你的專業需求會有很大的幫助
螢幕色彩偏離值只有0.98(校色後),未校色為1.17,1F最高為6.37(其餘都在1附近)
高達75%ARGB,116%SRGB。
表現已經達到頂級水平。


目前要顯示優秀的筆電(偏離值在1以下)非常的少,普遍都在2附近

MACBOOK PRO 13的螢幕表現
https://kknews.cc/zh-tw/digital/x2k6al8.html

菲律賓 正式中止 軍事訪問協定

https://youtu.be/DiFpRW_kw8g?t=2067

吹哨 的鬼邏輯 時間線

Coronavirus TIMELINE
https://www.youtube.com/watch?v=kO5EXjFKE7U


https://youtu.be/H0trgOgKFoE?t=716


https://youtu.be/DiFpRW_kw8g?t=1608


=============
我的美國公務員生活點滴 (番外篇2)
https://www.mobile01.com/topicdetail.php?f=651&t=5981610

沒有效果的運動方式 浪費時間的肌力訓練動作

6個浪費時間的肌力訓練動作

https://www.don1don.com/archives/23096/6%E5%80%8B%E6%B5%AA%E8%B2%BB%E6%99%82%E9%96%93%E7%9A%84%E8%82%8C%E5%8A%9B%E8%A8%93%E7%B7%B4%E5%8B%95%E4%BD%9C


1. 小腿上提 (Calf Raises)
替代方案:運動員應該讓他們的小腿肌自然發展,進行深蹲、跳蠅、還有日常的運動訓練就已經足夠了。

2.下斜式臥推 (Decline Bench Press)
替代方案:建議進行站姿滑輪胸推 (Standing Cable Presses),這個動作更接近於平日的運動形態

3.大腿推蹬機 (Leg Press)
替代方案:建議進行後腳抬高蹲 (Single-Leg Rear-Foot-Elevated Split Squats),因為大多數運動動作都是依靠單腳去進行,這個訓練動作正好乎合運動員的需求。

4.槓鈴彎舉 (Bicep Curls)
替代方案:對於想要讓手臂變強壯的運動員,引體向上 ( Pull-Ups)將會是一個比較好的選擇,另外也可以配合啞鈴或槓片來增加強度。

5.腿部伸展訓練機 (Machine Leg Extensions)
替代方案:建議採用前蹲舉(Front Squats)或跨步(Lunges),兩者都需要運動員去維持身體平衡,這在運動當中是一個非常重要的能力。

6.史密斯機器 (Smith Machine)
替代方案:採用自由重量 (Free Weight)進行深蹲、抓舉等動作將會為你身體的平衡帶來挑戰,如果做相同的重量覺得太重,那就換輕一點的吧!


反駁

https://james927.pixnet.net/blog/post/57606840


9種沒有效果的運動方式

http://www.unclesam.cc/blog/9-least-effective-exercises-from-webmd/

1. 頭後方的滑輪下拉(Lat Pull-down)
只有少數人有靈活的肩關節,讓他們在進行滑輪下拉時,能保持脊椎的直挺。所以在進行這個動作,若動作不正確時,將可能導致肩膀、旋轉肌群的受傷,若滑輪的槓子撞擊到頸部的後側,可能導致頸椎(cervical vertebrae)的受傷。

2. 槓鈴肩推舉(Military Press)
比較安全的方式是置於身體前側

3. 直立上提(Upright Row)
將槓鈴往上提至下巴處,真得不可行的方式(big no-no),這會壓迫到肩膀處的神經,衝擊到肩膀。

4. 大腿推蹬機,不適的膝蓋位置(Leg Press with Poor Knee Position)
在進行推蹬的動作,不要讓膝蓋過於前彎,超過90度,這你傷害到你的背部及膝蓋。

5. 利用史密斯機器輔助進行深蹲(Squats on the Smith Machine)
在使用史密斯機器來輔助時,人們往往會將腳步跨的更加前面。(換個方式說,藉由器材來進行訓練時,有的人會依著機器,但實際上姿勢跑掉或是受傷的機會就大大的提升)。

6. 在燃燒卡路里機器上的不良動作(Bad Form on Cardio Machines)
在使用燃燒卡路里的機器(跑步機),不要將坡度或阻力設定的太強,導致你要緊握著把手。設定在一個自然的狀況下,手握輕握著把手,讓你的身體能很自然、平衡下進行運動。

7. 局部的運動(Exercises for Spot Reduction)
人們透過局部的訓練來削減特定部位的脂肪,像是大腿、髖關節、胃及手臂,這是錯誤的想法,你不能把脂肪看成是一區一區的。有興趣的話,可以查查部落格上「迷思」的文章,對於脂肪有很多的說明囉。

避免使用健身房10種常見的訓練設備(二)

https://www.unclesam.cc/blog/10-exercise-machines-to-avoid-2/

6. 坐姿旋轉機(Seated Rotation Machine)
■ 實際的效用:「因為骨盆沒有跟著胸部移動,這個動作會施加過多的扭力在脊椎上。 」
■ 較好的動作:「砍木頭(Cable Wood Chop)」,讓你的腳踝跟著軀著活動,每邊進行10~12次。

7. 坐姿大腿推蹬機(Seated Leg Press Machine)
■ 實際的效用:「在沒有緊縮髖關節、臀肌、肩膀及下背部的必要的穩定肌肉之下, 這動作通常會強迫脊迫脊椎彎曲。」
■ 較好的動作:「徒手深蹲(Body-weight Squats Bischoff, Beth)」,在下背沒有拱起的狀況下,專注在下蹲的控制,1組進行12~15次,可以增加組數來訓練肌力

8. 史密斯機器(Smith Machine)
■ 實際的效用:「 槓子是固定在機器上,呈直接升降的移動方式,並非自然而有弧度的移動。這讓膝蓋、肩膀及下背帶來壓力。」
■ 較好的動作:「徒手深蹲(Body-weight squats)」,在下背沒有拱起的狀況下,專注在下蹲的控制,1組進行12~15次,可以增加組數來訓練肌力。

9. 羅馬背伸椅(Roman Chair Back Extension Machine)
■ 實際的效用:「 重複的彎曲你的背,而壓力加壓在脊椎上,增加椎間盤受損的風險。」
■ 較好的動作:「Bird-Dog」,四足跪姿,往前伸展右手臂及往後延伸左腳,重複進行7~10次,換邊進行。

10. 羅馬起坐椅(Roman Chair Sit-up)
■ 實際的效用:「捲腹的動作會將不必要的壓力落在下背部。」
■ 較好的動作:「棒式(Plank)」,維持20~60秒。

AI bot 聊天

https://mp.weixin.qq.com/s/CAs9AOPCDa3_yM1S-OfQxQ?fbclid=IwAR2UaV2ywyPoPY5_f3QMvj10rVaNryw_XhKhRlZFB-JlNT8QHdkOIzN4gOI

[轉]虛擬機跑起來!RouterOS CHR 軟路由效能輕鬆突破 1000M!

https://www.jkg.tw/?p=2531&fbclid=IwAR0TdjR76xT3k3w_bTNPfLZ8eW9Wuri9WBGJU7xoHsQo4PDUq2M5iIN4zfc

https://youtu.be/4PzJulQTSrY?t=1016

占美 i5 4278u

口罩

一開始四大超商就是政府決定的,怎麼決定出來不知道 (透明公開又沒了),到底誰規定一定要四大超商?!

政府絕對可以跟四大超商提出要求,口罩請用成本價售出,為了人民,至於四大超商評估是否要接這個案子

同時間其他的單位 一般藥局、連鎖藥局、全聯、屈沉世、大賣場、連鎖嬰幼、連鎖寵物等等通路,
政府絕對可以提出要求,口罩請用成本價售出,為了人民,他們可以評估是否要接這個案子

有人願意賠錢 做名聲、做善事就讓他做,互蒙其利,那來合理利潤,用合理利潤來談的話,每間通路成本不同,那我都用飛機來運口罩,一個賣200,運輸成本佔120,派人去各國搶購成本佔60,合理賺20,合理吧?! 為了合理,一堆漏洞就在裡面了!

特殊時期,你要賣,就給我照成本賣

說不定就一堆企業用成本賣,大打廣告,賺名聲


轉藥局為的是什麼? 用健保卡可以管理購買人! 而不是上面說的問題,用四大超商結果是一堆人買不到,現在的推論是有人一直買一直屯,真假比例誰知,真用 真屯?!

一開始說口罩不缺,實際缺的要死,完全能理解 政府本來在特定時期就需要說一些幹話,跟大陸一樣,在特殊時期也是要說說幹話:「中央已經掌握住情況,民眾無需恐荒」


要控制價格,讓民眾檢舉,噁心一點,做個網頁,讓民眾回報購買通路價格,做成歷史價格,用市場來打市場
要控制購買,要有手段能控制,健保卡,各通路會員制


想想這事還真的很難辨,照上做了,肯定又會發現上面的做法會有問題產生... 哈


==========

看大陸官方的說明比較準,之前說封城,實際上它的意思不是封城,是管制,我看繁華十年,實際上只要真的有親人,有人擔保,還有進入後隔離,就能進入了

致死率 妳如果有看我轉的論文,妳會發現
有的省份死亡率高到30%,大部份都是10%
我不知道我有沒有看錯
看29頁的圖,就會知道中獎和死亡 除非我搞錯意思
https://www.medrxiv.org/content/10.1101/2020.02.06.20020974v1.full.pdf

隨時都在變異,論文中提到的 超級感染者,這才是最可怕的

我到不覺得 一開始跟時間賽跑這個東西,我看AKA說的很清楚,我也非常能認同, 當疾症發生時,絕對不是看到黑影就開槍,實際上經過sars後,大陸已經有一套做法了,早已改了很多法令,為了這種情況,早在李文景發聲前,中國官方機構早就發現異常,但絕對不是我們想的,因為這個狀況從現在看來,從論文看來,很早就感染,而且不發燒,沒症狀,也能傳染,這怎麼防護?就算那時候用SARS的規格來防,沒用啊!因為沒發燒啊!連檢查ct都可能沒有異狀,看的越多越會覺得這個病很皮!

我都不看台灣報導,只看中國官方,然後結合yb上的相關內容,去掉 “情緒“ 來看,自然看的清,像妳剛說的,屍體燒不完,我大概都有看到新聞,我都直接略過,內容都懶得看了! 這種 屍體燒不完 ,大概就像我們sars時,我們彰化也在傳,那醫院半夜都有人進進出出一樣...呵呵

屍體燒不完 如果是真的話,香港、台灣早就也跟著燒不完了,因為 論文已經說的很明白了,沒有症狀!沒有症狀也能感染啊!連檢查都可能查不出來,怎麼防止!


年輕人不就醫也沒事的
最近看一個大陸yb,她老婆中獎,他自己照顧她老婆,應該撐過去了
https://youtu.be/9LOn5iBWRdc
還是不行,要住院

==========


https://www.youtube.com/watch?v=b-Fy80yHYQo

https://www.youtube.com/watch?v=_ZijOuFySgg


https://www.facebook.com/931837986851749/posts/2734799916555538/

https://www.facebook.com/931837986851749/posts/2736794659689397/


https://youtu.be/A75ivAVd-M0?t=1642
呵~~ 像候漢廷 fb的內容

>> 提高口罩的價格,才能阻卻不必要的搶購。才能促使商家願意增產。政府統一收購為0.94元,最終售價為8、6、5元,何來誘因使商家拚命生產?
>> 台灣所有口罩由政府統一收購,價格不高,阻卻商人販售回台。縱使事先即有執照者,同樣一批口罩,大陸售價高,台灣售價低,自然多數販售給大陸。
>> 無法轉賣毫無利潤,僅憑企業慈悲,難解問題。而國際代購業者售價必然高於台灣法定價格,台企業要嘛放棄購買,要嘛轉手倒賣。


https://youtu.be/KvcOb3bY9zk?t=337
大陸VS台灣領取口罩大PK|寒國人 底下討論也非常值得一看


韓國管制使用app 自主回報 還用app的gps來追
https://youtu.be/I2fn5lIM3ec?t=190 韓國用app回報


大陸買口罩的方式
https://www.youtube.com/watch?v=KvcOb3bY9zk&feature=youtu.be&t=337

===== 次氯酸水 =====



次氯酸VS漂白水 兩者一樣嗎?
「次氯酸HOCl」與「漂白水NaOCl」常被認為是相同的物質,但實際上他們是具有非常不同性質的兩種成分,現在就讓白博士來為大家解惑。

首先讓我們先來看一下化學式,雖然同樣具有「氧」和「氯」,但只要換了其中一個元素,如從「氫」變成「鈉」,就完全是另一個成分了。

以「酸鹼度」來看,次氯酸HOCl是弱酸性(pH<7);而漂白水NaOCl是鹼性(pH>7)。
殺菌能力就更不用說了,在相同濃度下,次氯酸HOCl的殺菌能力是漂白水NaOCl的100倍以上。

所以次氯酸與漂白水是看似相同卻是非常不同的成份。

http://www.honova.com/sabre.htm

https://www.youtube.com/watch?v=rRfmAMG5JBo

https://professorlin.com/2020/02/17/%E5%86%A0%E7%8B%80%E7%97%85%E6%AF%92%E6%9C%89%E5%A5%97%E8%86%9C%EF%BC%8C%E6%89%80%E4%BB%A5%E6%AC%A1%E6%B0%AF%E9%85%B8%E6%B0%B4%E7%84%A1%E6%95%88%EF%BC%9F/

====== =====
#武汉肺炎Q&A
#冠狀病毒 #CoronaVirus

感恩 抽空为我们解答

Q: #我需要戴口罩吗?
🅰普通口罩无法过滤病毒。如果你没有生病不需要戴口罩。但如果生病了就应该戴口罩,这样打喷嚏或者咳嗽的时候口水才不会到处飞。其实戴口罩不是为自己而是为别人戴。请把口罩让给真正需要的人。

Q:#遇到咳嗽的人立刻暂时停止呼吸、#马上远离有用吗?
🅰我们来不及提前知道他们几时要咳嗽打喷嚏,所以一旦他们突然打喷嚏咳嗽的时候,细菌病毒就马上到处飞,进入我们的鼻子/眼睛/嘴巴,感染我们的呼吸道。就算不呼吸/逃跑也是没用的。

Q:#此病毒存活可以多久?
🅰科学家还不知道它可以在表面上活多久。但是我们看普通的感冒病毒它能够在表面上活几个小时,如果我们打喷嚏在手上,过一个小时我们手上的病毒有可能感染别人。但也要看湿度,如果表面比较干,病毒会活得比较短。如果表面比较潮湿比如有口水/鼻涕,病毒就会活得比较久。

Q:#干洗手消毒凝胶VS肥皂水哪一个比较好?
🅰肥皂水更快更方便因为只需要20秒就可以把全部病毒给毁灭掉。但是在外不方便的话,用干洗手消毒凝胶的时候确保手是干的才有效,如果手湿湿的话,那些流感病毒有可能不会被毁灭掉。如果要把所有病毒给毁灭掉就要等4分钟,才会把病毒给完全毁灭掉。

Q:#家中的宠物会感染2019新冠状病毒吗?
🅰狗/猫不会被感染,也不会传播给人。最近没有报告显示狗/猫传染给人。

Q:#我会因为来自中国的物品而被感染吗?
🅰不会。因为病毒不会在包裹上活得那么久,而且也没有报告显示有人因为包裹而受感染。

Q:#低温利于病毒存活?#所以天气越温暖越有利疫情控制?
🅰病毒不喜欢热,遇到60多度就会死亡,遇到潮湿空气就会变重掉下来不会漂浮在空气。所以马来西亚的天气比较不利于病毒的传播。

Q:#2019新冠状病毒与其他大规模爆发性传染病的比较
🅰死亡率只有2%。比其他的爆发性传染病低很多,所以不必担心,很多人都开始慢慢痊愈。此疾病死亡的人都是因为年纪比较大/有其他疾病比如心脏病或肺部疾病,他们的免疫力比较弱,所以比较难康复。

Q: #有疫苗可以帮助这个病毒吗 ?
🅰很难有疫苗因为它突变太快了
(科学家已发现病毒在变异了)

Q: #空气清净机可以过滤病毒吗❓
🅰不能,因为病毒是很小很小的

**以上资料来自 讲座笔记

flutter build release

https://medium.com/flutterpub/flutter-andorid-keystore-path-on-different-os-d0fc30a24d4f

https://blog.csdn.net/joye123/article/details/94588949


signingConfig signingConfigs.release

Important is signingConfig signingConfigs.debug -> signingConfig signingConfigs.release




    signingConfigs {
       release {
           keyAlias keystoreProperties['keyAlias']
           keyPassword keystoreProperties['keyPassword']
           storeFile keystoreProperties['storeFile'] ? file(keystoreProperties['storeFile']) : null
           storePassword keystoreProperties['storePassword']
       }
    }
    buildTypes {
        release {
            // TODO: Add your own signing config for the release build.
            // Signing with the debug keys for now, so `flutter run --release` works.
            signingConfig signingConfigs.release

            minifyEnabled true
            useProguard true
        }
    }
}

flutter create project name com.xxx.xxx

https://stackoverflow.com/questions/51534616/how-to-change-package-name-in-flutter
https://medium.com/@skyblazar.cc/how-to-change-the-package-name-of-your-flutter-app-4529e6e6e6fc



EDITED : 27-Dec-18

for package name just change in build build.gradle only


defaultConfig {
    applicationId "your.package.name"
    minSdkVersion 16
    targetSdkVersion 27
    versionCode 1
    versionName "1.0"
    testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}



flutter create --org com.yourdomain appname

golang loggin gin

https://github.com/uber-go/zap

https://marcoma.xyz/2019/03/17/gin-tutorial-7/

https://github.com/natefinch/lumberjack

https://juejin.im/post/5d3932bde51d454f73356e2d

function widget or widget StatelessWidget

https://codertw.com/%E7%A8%8B%E5%BC%8F%E8%AA%9E%E8%A8%80/644148/

拆分widget

永遠不要使用方法返回的形式創建可重用的widget,始終將它們封裝到StatelessWidget中。 注意這個結論中的可重用。

[轉]职场困惑:我该怎么办?

https://www.v2ex.com/t/637213 這討論蠻不錯的


看了楼主的回复,我觉得你存在一个非常典型的思维方式: 我自己称为借斧子(参考这个里面的第一个故事: http://news.sina.com.cn/o/2018-01-07/doc-ifyqiwuw7820642.shtml )
很多人喜欢猜,猜别人的想法,别人的动机,给自己预设很多条件,然后在这个限制中拼命挣扎。无论你怎么去预设你老大的思维,都不及你去和他当面深入交流一下。无论结局如何,聊完,你基本上可以获得你想要的答案:
1. 如果老大告诉你绩效 B 的原因: 这个最好
2. 老板告诉你一个你不能接受的原因: 你们经过争论是否能统一思想,如果不能,说明你和老大思路不和,要不改变自己,要不就换个老大
3. 老大不告诉你: 说明你不可能拿到 A 了,你该换工作了

最后,注意和老大及时高频率的沟通,注意不是去拍马屁,不是去出风头,而是去实实在在的沟通工作内容,任何工作相关的东西都可以,保持几天一次一对一沟通的频率,能够让你和老大的关系提升许多。不要觉得不想厚黑就不去主动找老大聊工作,没有那么多非黑即白的东西

ethereum docker geth shell for geth attach and tail log

Help use docker geth for geth attach and watch log. Geth Command line path need to change for yourself env.



#!/bin/sh
IFS=$'\n'
echo $1
echo $2

case $2 in
    attach) docker exec -it $(docker ps -a --no-trunc  | grep $1 | awk '{print $1}') geth attach --datadir=/root/.ethereum/devchain
        ;;
    log) docker exec -it $(docker ps -a --no-trunc  | grep $1 | awk '{print $1}') tail -n 30 -f /root/geth.log
        ;;
    sh) docker exec -it $(docker ps -a --no-trunc  | grep $1 | awk '{print $1}') sh
        ;;
    bash) docker exec -it $(docker ps -a --no-trunc  | grep $1 | awk '{print $1}') bash
        ;;
    *)  echo "command parms1: docker container name"
        echo "command parms2: attach (geth attach) or log (tail -n 30 -f) or sh or bash"
esac

[轉]如何為LINUX, WINDOWS容器加入憑證?

https://blog.kkbruce.net/2020/01/linux-windows-container-add-cert.html?fbclid=IwAR0d_LhzAYwatOZ-Ibl4mK7Ne-iAViwKT_UWcj0Wg52YlHTKzSFNDWcp-Hk#more

ubuntu

/usr/local/share/ca-certificates
update-ca-certificates


windows

Import-Certificate -FilePath ooxx   -CertStoreLocation ooxx


How to test your self ethereum geth private poa truffle part2

every sec send transaction nonce++

https://medium.com/finnovate-io/how-do-i-sign-transactions-with-web3-f90a853904a2
https://ethereum.stackexchange.com/questions/60611/defining-the-transaction-object-for-offline-transaction-signing-using-web3-js-f
https://github.com/ethereum/web3.js/issues/1430

https://programtheblockchain.com/posts/


signTransaction(tx, "0x"+privateKey) "0x" privatekey need becarful.


--ws --wsaddr 0.0.0.0 --wsorigins "*" --wsapi "db,admin,debug,miner,eth,net,web3,network,txpool"


var fs  = require('fs');

var Web3 = require("web3");
var provider = new Web3.providers.HttpProvider("http://192.168.99.100:18545");
var wsprovider = new Web3.providers.WebsocketProvider("ws://192.168.99.100:18546");
//var web3 = new Web3(provider);
var web3 = new Web3(wsprovider);

console.log("before web set account: %o", web3.eth.defaultAccount);
const privateKey = '138cbbfb21686ddc3b5ffeb2cfc83491175af68319977acb81d0ae93392c626c';
const account = web3.eth.accounts.privateKeyToAccount('0x' + privateKey);
//web3.eth.accounts.wallet.add(account);
//console.log("private key import to account: %o", account.address)
web3.eth.defaultAccount = account.address;

// try {
//     web3.eth.personal.unlockAccount(account.address, "").then(console.log('Account unlocked!'));
// } catch (err) {
//     console.error('web3 unlockAccount Error: %o', err);
// }

var certjson;
var certjsonpath = './Cert.json';

try {
    certjson = JSON.parse(fs.readFileSync(certjsonpath));
} catch (err) {
    console.error('readFileSync Error: %o', err);
}

var contractjson;
var contractjsonpath = './MetaCoin.json';

try {
    contractjson = JSON.parse(fs.readFileSync(contractjsonpath));
} catch (err) {
    console.error('readFileSync Error: %o', err);
}


const getNonce = () => {
    return new Promise((resolve, reject) => {
        web3.eth.getTransactionCount(web3.eth.defaultAccount, 'pending', (error, result) => {
            if(error) reject(error);
            resolve(web3.utils.toHex(result));
        })
    })
}

const getGasPrice = () => {
    return new Promise((resolve, reject) => {
        web3.eth.getGasPrice((error, result) => {
            if(error) reject(error);
            resolve(web3.utils.toHex(result));
        })
    })
}

const createContract = (contractfrom_caller, nonce="") => {
    return new Promise((resolve, reject) => {
        const tx = {
            from: contractfrom_caller, 
            gasPrice: web3.utils.toHex(web3.utils.toWei('2', 'gwei')), //20,000,000,000
            gas: web3.utils.toHex('6819490'),
            //gasLimit: 9000000,
            value: '0x00', // web3.utils.toHex('0'),
            data: certjson.bytecode
        };
        
        if(nonce!="") { tx.nonce = nonce; console.log("tx: %o", tx); }
        
        // const keystore = "Contents of keystore file";
        // const decryptedAccount = web3.eth.accounts.decrypt(keystore, 'PASSWORD');
        // web3.eth.accounts.signTransaction(rawTransaction, decryptedAccount.privateKey)
        //  .then(console.log);
        // OR
        // decryptedAccount.signTransaction(tx)
        
        //const signPromise = web3.eth.accounts.signTransaction(tx, "0x"+privateKey);
        web3.eth.accounts.signTransaction(tx, "0x"+privateKey)
        .then(resolve)
        .catch(reject);
    })
}


const getBalance = (contractAddr, coinOwnerAddr) => {
    return new Promise((resolve, reject) => {
        web3.eth.call({
            to: contractAddr,
            data: metaCoinContract.methods.getBalance(coinOwnerAddr).encodeABI()
        })
        .then(resolve)
        .catch(reject);
        // .then(o => {
        //     resolve(o);
        // })
        // .catch((error) => {
        //     reject(error)
        // });
    })
}

const sendCoin = (contractAddr, sendCointoAddr, coinNumber, nonce="") => {
    return new Promise((resolve, reject) => {
        const tx = {
            from: contractfrom_caller, 
            to: contractAddr, 
            gasPrice: web3.utils.toHex(web3.utils.toWei('2', 'gwei')), //20,000,000,000
            gas: web3.utils.toHex('181949'),
            //gasLimit: 9000000,
            value: '0x00', // web3.utils.toHex('0'),
            data: metaCoinContract.methods.sendCoin(sendCointoAddr, coinNumber).encodeABI() 
        };
        
        if(nonce!="") { tx.nonce = nonce; console.log("tx: %o", tx); }
        
        // const keystore = "Contents of keystore file";
        // const decryptedAccount = web3.eth.accounts.decrypt(keystore, 'PASSWORD');
        // web3.eth.accounts.signTransaction(rawTransaction, decryptedAccount.privateKey)
        //  .then(console.log);
        // OR
        // decryptedAccount.signTransaction(tx)
        
        //const signPromise = web3.eth.accounts.signTransaction(tx, "0x"+privateKey);
        web3.eth.accounts.signTransaction(tx, "0x"+privateKey)
        .then(resolve)
        .catch(reject);
    })
}

contractAddr = "0x3Da963B807bF892F7A10B61E9ffD830068f8C23d";
contractfrom_caller = "0xe79d33e93bd888b35e055f1a12d876354729037b";
coinOwnerAddr = "0xe79d33e93bd888b35e055f1a12d876354729037b"
sendCointoAddr = "0x5921a4C1B13afbD4b61d63e9c7BD47741C47B176";

const metaCoinContract = new web3.eth.Contract(contractjson.abi, contractAddr);

// getBalance
// web3.eth.call({
//     to: contractAddr,
//     data: metaCoinContract.methods.getBalance(coinOwnerAddr).encodeABI()
// })
// .then(o => {
//     console.log("%s getBalance at %s contract: %o", coinOwnerAddr, contractAddr, web3.utils.hexToNumberString(o))
// });
getBalance(contractAddr, coinOwnerAddr)
.then(o => { console.log("%s getBalance at %s contract: %o", coinOwnerAddr, contractAddr, web3.utils.hexToNumberString(o)) })
.catch((error) => { console.log("getBalance catch error: %o", error.message); });


// transfor coin
// const signPromise = sendCoin(contractAddr, sendCointoAddr, 10);
// signPromise.then((signedTx) => {
//     const sentTx = web3.eth.sendSignedTransaction(signedTx.raw || signedTx.rawTransaction);

//     sentTx.on("receipt", receipt => {
//         console.log("receipt: %o", receipt);
//         console.log("receipt.contractAddress: %o", receipt.contractAddress);
//     });

//     sentTx.on("error", error => {
//         console.log("sendSignedTransaction error: %o", error.message);
//     })
    
//     sentTx.then(o => {
//         TxHash = o.transactionHash;
//         console.log("##### TxHash: %o", TxHash)
//     });
// }).catch((error) => {
//     console.log("sendSignedTransaction catch error: %o", error.message);
// });

// getBalance coin sender & reciver
getBalance(contractAddr, coinOwnerAddr)
.then(o => { console.log("coinOwnerAddr %s getBalance at %s contract: %o", coinOwnerAddr, contractAddr, web3.utils.hexToNumberString(o)) })
.catch((error) => { console.log("getBalance catch error: %o", error.message); });

getBalance(contractAddr, sendCointoAddr)
.then(o => { console.log("sendCointoAddr %s getBalance at %s contract: %o", coinOwnerAddr, contractAddr, web3.utils.hexToNumberString(o)) })
.catch((error) => { console.log("getBalance catch error: %o", error.message); });


Promise.all([getNonce(), getGasPrice()]).then(values => {
    
    var nonce = web3.utils.hexToNumberString(values[0]);
    console.log("Nonce: %o", nonce);

    createContract(contractAddr, web3.utils.toHex(nonce)).then((signedTx) => {
        console.log('createContract signedTx: %o', signedTx);
        const sentTx = web3.eth.sendSignedTransaction(signedTx.raw || signedTx.rawTransaction);
        sentTx.then(o => {
            TxHash = o.transactionHash;
            console.log("##### createContract TxHash: %o", TxHash);

            web3.eth.getTransactionReceipt(TxHash).then(o=>{
                console.log("check contractAddress object: %s", o.contractAddress); 
            });    
        })
        .catch((error) => { console.log("createContract sendSignedTransaction catch error: %o", error.message); });
    }).catch((error) => { console.log("screateContract catch error: %o", error.message); });

    nonce++;

    setInterval( () => {
    
    sendCoin(contractAddr, sendCointoAddr, 10, web3.utils.toHex(nonce)).then((signedTx) => {
        console.log('sendCoin 3 signedTx: %o', signedTx);
        const sentTx3 = web3.eth.sendSignedTransaction(signedTx.raw || signedTx.rawTransaction);
        sentTx3.then(o => {
            TxHash = o.transactionHash;
            console.log("##### sendCoin 3 TxHash: %o", TxHash);
        })
        .catch((error) => { console.log("sendCoin 3 catch error: %o", error.message); });
    }).catch((error) => { console.log("sendSignedTransaction3 catch error: %o", error.message); });
    
    nonce++;
    console.log("Nonce: %o", nonce);

    getBalance(contractAddr, coinOwnerAddr)
    .then(o => { console.log("coinOwnerAddr %s getBalance at %s contract: %o", coinOwnerAddr, contractAddr, web3.utils.hexToNumberString(o)) })
    .catch((error) => { console.log("getBalance catch error: %o", error.message); });

    getBalance(contractAddr, sendCointoAddr)
    .then(o => { console.log("sendCointoAddr %s getBalance at %s contract: %o", coinOwnerAddr, contractAddr, web3.utils.hexToNumberString(o)) })
    .catch((error) => { console.log("getBalance catch error: %o", error.message); });

    }, Math.random() * 1000);
})
.then(console.log("Promise all transaction ok!"))
.catch(e => console.log("promise all error: %o", e.message))   

// sendCoin(contractAddr, sendCointoAddr, 10).then((signedTx) => {
//     console.log('sendCoin 2 signedTx: %o', signedTx);
//     const sentTx2 = web3.eth.sendSignedTransaction(signedTx.raw || signedTx.rawTransaction);
//     sentTx2.then(o => {
//         TxHash = o.transactionHash;
//         console.log("##### sendCoin 2 TxHash: %o", TxHash)
//     })
//     .catch((error) => { console.log("sendCoin 2 catch error: %o", error.message); });
// }).catch((error) => { console.log("sendSignedTransaction2 catch error: %o", error.message); });

// sendCoin(contractAddr, sendCointoAddr, 10).then((signedTx) => {
//     console.log('sendCoin 3 signedTx: %o', signedTx);
//     const sentTx3 = web3.eth.sendSignedTransaction(signedTx.raw || signedTx.rawTransaction);
//     sentTx3.then(o => {
//         TxHash = o.transactionHash;
//         console.log("##### sendCoin 3 TxHash: %o", TxHash)
//     })
//     .catch((error) => { console.log("sendCoin 3 catch error: %o", error.message); });
// }).catch((error) => { console.log("sendSignedTransaction3 catch error: %o", error.message); });

//metaCoinContract.events.allEvents()
metaCoinContract.events.Transfer()
.on('data', function(event){
    console.log("##### events data: %o", event); // same results as the optional callback above
})
.on('changed', function(event){
    console.log("##### events changed: %o", event);
})
.on('error', console.error);

metaCoinContract.getPastEvents('Transfer', function(error, events){ console.log("##### getPastEvents changed: %o", events); })
.then(function(events){
    console.log("##### getPastEvents changed: %o", events) // same results as the optional callback above
});

修行

你從那裡來? 妄想從那裡來?

心自體不可得,作用可得

開顯自己的真如本性
修行從裡面(內在)生起,這個心誰都不能破壞

印光大師說:全世界的人念佛都沒有感應,全世界的人念佛都沒求生淨土,我照樣念佛,我照樣求生淨土

跟外境沒有關係

不生滅心

https://youtu.be/iudlojChsKs?list=PLA16E144975D1AFCD&t=1963



修正自己的行為

[轉]解決replacement transaction underpriced以太坊交易異常

https://www.twblogs.net/a/5bb2596a2b71770e645ddc3c

replacement transaction underpriced異常

問題概述

以太坊系列(ETH&ETC)在發送交易有三個對應的RPC接口,分別是ethsendTransaction、ethsendRawTransaction和personal_sendTransaction。這三個接口發送(或構造發送內容時)都需要一個參數nonce。官方文檔對此參數的解釋是:整數類型,允許使用相同隨機數覆蓋自己發送的處於pending狀態的交易。

僅從官網的解釋,我們無法獲取到更多的有效的信息。但在真實生成中我們會發現如果傳錯nonce字段值,通過RPC接口調用發送的交易很大可能將不會被確認。如果通過console命令來操作一般不會出現此問題,因爲節點已經幫我們處理了。

如果繼續追蹤問題,會發現nonce傳遞錯誤的交易可以通過eth_getTransaction查詢得到相關信息,但是它的blocknumber始終未null,也就說這邊交易始終未被確認。如果是在dev模式下,應該是很快就會被確認的。更進一步,通過txpool.content命令,會發現那筆交易一直處於queued隊列中,而未被消費。

在使用同一個地址連續發送交易時,每筆交易往往不可能立即到賬, 當前交易還未到賬的情況下,下一筆交易無論是通過eth.getTransactionCount()獲取nonce值來設置,還是由節點自動從區塊中查詢,都會獲得和前一筆交易同樣的nonce值,這時節點就會報錯Error: replacement transaction underpriced

爲了防止交易重播,ETH(ETC)節點要求每筆交易必須有一個nonce數值。每一個賬戶從同一個節點發起交易時,這個nonce值從0開始計數,發送一筆nonce對應加1。當前面的nonce處理完成之後纔會處理後面的nonce。注意這裏的前提條件是相同的地址在相同的節點發送交易。 以下是nonce使用的幾條規則:

● 當nonce太小(小於之前已經有交易使用的nonce值),交易會被直接拒絕。

● 當nonce太大,交易會一直處於隊列之中,這也就是導致我們上面描述的問題的原因;

● 當發送一個比較大的nonce值,然後補齊開始nonce到那個值之間的nonce,那麼交易依舊可以被執行。

● 當交易處於queue中時停止geth客戶端,那麼交易queue中的交易會被清除掉。

如果系統中的熱點賬戶或普通賬戶發起交易時出現error: replacement transaction underpriced異常,那麼就需要考慮nonce使用是否正確。

引起此異常原因主要是當一個賬戶發起一筆交易,假設使用nonce爲1,交易已經發送至節點中,但由於手續費不高或網絡擁堵或nonce值過高,此交易處於queued中遲遲未被打包。

同時此地址再發起一筆交易,如果通過eth_getTransactionCount獲取的nonce值與上一個nonce值相同,用同樣的nonce值再發出交易時,如果手續費高於原來的交易,那麼第一筆交易將會被覆蓋,如果手續費低於原來的交易就會發生上面的異常。

通常發生此異常意味着:
- 你的Ethereum客戶端中已經有一筆處於pending狀態的交易。
- 新的一筆交易擁有pending狀態交易相同的nonce值。

- 新的交易的gas price太小,無法覆蓋pending狀態的交易。

通常情況下,覆蓋掉一筆處於pending狀態的交易gas price需要高於原交易的110%。

經過上面的解釋追蹤,我們已經瞭解到了nonce的基本使用規則。那麼,在實際應該用中我們如何保障nonce值的可靠性呢?這裏有兩個思路,

第一個思路就是由業務系統維護nonce值的遞增。如果交易發送就出現問題,那麼該地址下一筆交易繼續使用這個nonce進行發送交易。


第二個思路就是使用現有的api查詢當前地址已經發送交易的nonce值,然後對其加1,再發送交易。對應的API接口爲:eth_getTransactionCount,此方法由兩個參數,第一個參數爲需要查詢nonce的地址,第二個參數爲block的狀態:latest、earliest和pending。一般情況使用pending就可以查詢獲得最新已使用的nonce。其他狀態大家可以自行驗證。


第三個思路就
如果該熱點賬戶的私鑰信息等都存放在Ethereum客戶端中,那麼在發送交易的時候不傳遞nonce值,Ethereum客戶端會幫你處理好此nonce值的排序。


當然,此方案有兩個弊端。第一個是安全性無法保障(未進行冷熱賬戶分離),第二,在熱點賬戶下如果想覆蓋掉一筆交易,需要先查詢一下該交易的信息,從中獲取nonce值。

第一個思路

自行管理nonce適用於冷熱賬戶模式,也就是適用sendRawTransaction發送已經簽名好的交易時,此時nonce值已經存在於交易中,並且已經被簽名。

這種模式下,需要在業務系統中維護nonce的自增序列,使用一個nonce之後,在業務系統中對nonce進行加一處理。

此種方案也有限制條件。第一,由於nonce統一進行維護,那麼這個地址必須是內部地址,而且發起交易必須通過統一維護的nonce作爲出口,否則在其他地方發起交易,原有維護的nonce將會出現混亂。第二,一旦已經發出的交易發生異常,異常交易的nonce未被使用,那麼異常交易的nonce需要重新被使用之後它後面的nonce纔會生效。

在構建一筆新的交易時,在交易數據結構中會產生一個nonce值, nonce是當前區塊鏈下,發送者(from地址)發出的交易(成功記錄進區塊的)總數, 再加上1。例如新構建一筆從A發往B的交易,A地址之前的交易次數爲10,那麼這筆交易中的nonce則會設置成11, 節點驗證通過後則會放入交易池(txPool),並向其他節點廣播,該筆交易等待礦工將其打包進新的區塊。

第二個思路

那麼,如果在先構建併發送了一筆從地址A發出的,nonce爲11的交易,在該交易未打包進區塊之前, 再次構建一筆從A發出的交易,並將它發送到節點,不管是先通過web3的eth.getTransactionCount(A)獲取到的過往的交易數量,還是由節點自行填寫nonce, 後面的這筆交易的nonce同樣是11, 此時就出現了問題:

後面的這筆交易手續費給得更高, 那麼節點會前面的那筆交易從交易池中剔除,轉而放入後面構建的這筆交易
如果後面的這筆交易給得不夠高, 就會被廢棄掉, 如果通過web3這樣的sdk來向節點發送交易時,會收到錯誤信息

實際場景中

,會有批量從一個地址發送交易的需求,首先這些操作可能也應該是並行的,我們不會等待一筆交易成功寫入區塊後再發起第二筆交易,那麼此時有什麼好的解決辦法呢?先來看看geth節點中交易池對交易的處理流程

如之前所說,

第三個思路

構建一筆交易時如果不手動設置nonce值,geth節點會默認計算發起地址此前最大nonce數(寫入區塊的才算數),然後將其加上1, 然後將這筆交易放入節點交易池中的pending隊列,等到節點將其打包進區塊。

第一個思路

構建交易時,nonce值是可以手動設置的,如果當前的nonce本應該設置成11, 但是我手動設置成了13, 在節點收到這筆交易時, 發現pending隊列中並沒有改地址下nonce爲11及12的交易, 就會將這筆nonce爲13的交易放入交易池的queued隊列中。只有當前面的nonce補齊(nonce爲11及12的交易被發現並放入pending隊列)之後,纔會將它放入pending隊列中等待打包。

我們把pending隊列中的交易視爲可執行的,因爲它們可能被礦工打包進最新的區塊。 而queue隊列因爲前面的nonce存在缺失,暫時無法被礦工打包,稱爲不可執行交易。

那麼

實際開發中
,批量從一個地址發送交易時,應該怎麼辦呢?


方案一:

那麼在批量從一個地址發送交易時, 可以持久化一個本地的nonce,構建交易時用本地的nonce去累加,逐一填充到後面的交易。(要注意本地的nonce可能會出現偏差,可能需要定期從區塊中重新獲取nonce,更新至本地)。這個方法也有一定的侷限性,適合內部地址(即只有這個服務會使用該地址發送交易)。

說到

這裏還有個坑

,許多人認爲通過eth.getTransactionCount(address, "pending"),第二個參數爲pending, 就能獲得包含本地交易池pending隊列的nonce值,但是實際情況並不是這樣, 這裏的pending只包含待放入打包區塊的交易, 假設已寫入交易區塊的數量爲20, 又發送了nonce爲21,22,23的交易, 通過上面方法取得nonce可能是21(前面的21,22,23均未放入待打包區塊), 也可能是22(前面的21放入待打包區塊了,但是22,23還未放入)。

新版本的Geth好像解決了這個問題,在超大量測試transaction中,沒發現上述情況,如這問題還在應該會是大量錯誤一直產生才對!

超大量測試transaction

方案二:

是每次構建交易時,從geth節點的pending隊列取到最後一筆可執行交易的nonce, 在此基礎上加1,再發送給節點。可以通過txpool.content或txpool.inspect來獲得交易池列表,裏面可以看到pending及queue的交易列表。

其他方式:

啓動節點時,是可以設置交易池中的每個地址的pending隊列的容量上限,queue隊列的上容量上限, 以及整個交易池的pending隊列和queue隊列的容量上限。所以高併發的批量交易中,需要增加節點的交易池容量。

當然,除了擴大交易池,控制發送頻率,更要設置合理的交易手續費,eth上交易寫入區塊的速度取決於手續費及eth網絡的擁堵狀況,發送每筆交易時,設置合理的礦工費用,避免大量的交易積壓在交易池。

How to test your self ethereum geth private poa truffle

Important!! web3.eth.sendTransaction({ data: bytecode

"certjson.bytecode" or "certjson.bytecode.object"

MUST Have "0x" at line First Character


Use Truffle


1. run https://www.trufflesuite.com/docs/truffle/quickstart

1-1. run command


mkdir testtruffle
cd testtruffle
npm i web3

truffle unbox metacoin
truffle test ./test/TestMetaCoin.sol
truffle test ./test/metacoin.js
truffle compile

2. modify truffle-config.js
Here use your private poa chain networkinfo. from address must be can used. genesis file can put this address.


module.exports = {
  // Uncommenting the defaults below 
  // provides for an easier quick-start with Ganache.
  // You can also follow this format for other networks;
  // see 
  // for more details on how to specify configuration options!
  //
  networks: {
    development: {
      host: "192.168.99.100",
      port: 8545,
      network_id: "*",
      from: "0x5921a4c1b13afbd4b61d63e9c7bd47741c47b176"
    },
  //  test: {
  //    host: "127.0.0.1",
  //    port: 7545,
  //    network_id: "*"
  //  }
  }
  
};

3. modify migrations/1_initial_migration.js

If account have password, remark some line to put password. Here example no password.

Import: importRawKey maybe run one time, get error msg "Error: Returned error: account already exists" then remark.


Import: if unlock failed, may be is geth new version need to add --allow-insecure-unlock



const Web3 = require('web3');
const TruffleConfig = require('../truffle-config.js');

const Migrations = artifacts.require("Migrations");

module.exports = function(deployer) {
  const config = TruffleConfig.networks.development;

  //if (process.env.ACCOUNT_PASSWORD) {
    const web3 = new Web3(new Web3.providers.HttpProvider('http://' + config.host + ':' + config.port));

    // maybe only run one time for geth
    // web3.eth.personal.importRawKey('d05bd152f3d71ff5f91830f3ccc1090fb670c7026ebf8c2136d4e5090d59398d', '')
    // web3.eth.personal.importRawKey('138cbbfb21686ddc3b5ffeb2cfc83491175af68319977acb81d0ae93392c626c', '')

    // if unlock failed, may be is geth new version need to add --allow-insecure-unlock 
    console.log('>> Unlocking account ' + config.from);
    // //web3.personal.unlockAccount(config.from, process.env.ACCOUNT_PASSWORD, 36000);
    web3.eth.personal.unlockAccount(config.from, '', 36000);
  //}

  console.log('>> Deploying migration');

  deployer.deploy(Migrations);
};


truffle migrate


4. run

truffle test

Why you need to do this, because you can run many test (open 3 or more command line run truffle test) on same time for test your private poa ethereum.

If see Error, next step.


5. modify test/metacoin.js check code like this:


const MetaCoin = artifacts.require("MetaCoin");

Check accounts who have coin then change balance 0 or 1 & account one or two.

contract('MetaCoin', (accounts) => {
  it('should put 10000 MetaCoin in the first account', async () => {
    const metaCoinInstance = await MetaCoin.deployed();
    console.log('\n accounts: %o\n', accounts);
    
    const balance0 = await metaCoinInstance.getBalance.call(accounts[0]);
    const balance1 = await metaCoinInstance.getBalance.call(accounts[1]);
    console.log('balance0: %s', balance0.valueOf());
    console.log('balance1: %s\n', balance1.valueOf());

    assert.equal(balance1.valueOf(), 10000, "10000 wasn't in the first account");
  });
  it('should call a function that depends on a linked library', async () => {
    const metaCoinInstance = await MetaCoin.deployed();
    const metaCoinBalance = (await metaCoinInstance.getBalance.call(accounts[0])).toNumber();
    const metaCoinEthBalance = (await metaCoinInstance.getBalanceInEth.call(accounts[0])).toNumber();

    assert.equal(metaCoinEthBalance, 2 * metaCoinBalance, 'Library function returned unexpected function, linkage may be broken');
  });
  it('should send coin correctly', async () => {
    const metaCoinInstance = await MetaCoin.deployed();

    // Setup 2 accounts.
    const accountOne = accounts[1];
    const accountTwo = accounts[0];

    // Get initial balances of first and second account.
    const accountOneStartingBalance = (await metaCoinInstance.getBalance.call(accountOne)).toNumber();
    const accountTwoStartingBalance = (await metaCoinInstance.getBalance.call(accountTwo)).toNumber();

    // Make transaction from first account to second.
    const amount = 10;
    await metaCoinInstance.sendCoin(accountTwo, amount, { from: accountOne });

    // Get balances of first and second account after the transactions.
    const accountOneEndingBalance = (await metaCoinInstance.getBalance.call(accountOne)).toNumber();
    const accountTwoEndingBalance = (await metaCoinInstance.getBalance.call(accountTwo)).toNumber();


    assert.equal(accountOneEndingBalance, accountOneStartingBalance - amount, "Amount wasn't correctly taken from the sender");
    assert.equal(accountTwoEndingBalance, accountTwoStartingBalance + amount, "Amount wasn't correctly sent to the receiver");
  });
});


===========

web3 private key unlock & create contract


createcontract.js methond 1

var fs  = require('fs');

var Web3 = require("web3");
var provider = new Web3.providers.HttpProvider("http://192.168.99.100:18545");
var web3 = new Web3(provider);

console.log("before web set account: %o", web3.eth.defaultAccount);
const privateKey = 'd05bd152f3d71ff5f91830f3ccc1090fb670c7026ebf8c2136d4e5090d59398d';
const account = web3.eth.accounts.privateKeyToAccount('0x' + privateKey);
web3.eth.accounts.wallet.add(account);
console.log("private key import to account: %o", account)
web3.eth.defaultAccount = account.address;

try {
    web3.eth.personal.unlockAccount(account.address, "").then(console.log('Account unlocked!'));
} catch (err) {
    console.error('web3 unlockAccount Error: %o', err);
}

var certjson;
var certjsonpath = './Cert.json';

try {
    certjson = JSON.parse(fs.readFileSync(certjsonpath));
} catch (err) {
    console.error('readFileSync Error: %o', err);
}

const certContract = new web3.eth.Contract(certjson.abi);
certContract.options.data = certjson.bytecode;
certContract.options.from = '0x5921a4C1B13afbD4b61d63e9c7BD47741C47B176'
certContract.options.gas = '4700000'

console.log("web3 version: %o", web3.version)
web3.eth.getAccounts().then(o=>{console.log("Accounts: %o", o)})

certContract.deploy().send()
.on('error', (error) => {
    console.log("error: %o", error)
})
.on('transactionHash', (transactionHash) => {
    console.log("transactionHash: %o", transactionHash)
})
.on('receipt', (receipt) => {
    // receipt will contain deployed contract address
    console.log("receipt: %o", receipt)
    console.log("receipt.contractAddress: %o", receipt.contractAddress) 
})
.on('confirmation', (confirmationNumber, receipt) => {
    console.log("confirmationNumber: %o", confirmationNumber)
    console.log("confirmation receipt: %o", receipt)
})
.then(function(newContractInstance){
    if (typeof newContractInstance.options.address !== 'undefined') {
        console.log('Contract mined! address: ' + newContractInstance.options.address);
    }else{
        console.log("newContractInstance.address is undefined!")
    }
});

createcontract.js methond 2

var fs  = require('fs');

var Web3 = require("web3");
var provider = new Web3.providers.HttpProvider("http://192.168.99.100:18545");
var web3 = new Web3(provider);

console.log("before web set account: %o", web3.eth.defaultAccount);
const privateKey = 'd05bd152f3d71ff5f91830f3ccc1090fb670c7026ebf8c2136d4e5090d59398d';
const account = web3.eth.accounts.privateKeyToAccount('0x' + privateKey);
web3.eth.accounts.wallet.add(account);
console.log("private key import to account: %o", account)
web3.eth.defaultAccount = account.address;

try {
    web3.eth.personal.unlockAccount(account.address, "").then(console.log('Account unlocked!'));
} catch (err) {
    console.error('web3 unlockAccount Error: %o', err);
}

var certjson;
var certjsonpath = './Cert.json';

try {
    certjson = JSON.parse(fs.readFileSync(certjsonpath));
} catch (err) {
    console.error('readFileSync Error: %o', err);
}

const certContract = new web3.eth.Contract(certjson.abi);
certContract.options.data = certjson.bytecode;
certContract.options.from = '0x5921a4C1B13afbD4b61d63e9c7BD47741C47B176'
certContract.options.gas = '4700000'

console.log("web3 version: %o", web3.version)
web3.eth.getAccounts().then(o=>{console.log("Accounts: %o", o)})

// 怖署合約
var TxHash;

console.log("######## promise all ##############");

const getNonce = () => {
    return new Promise((resolve, reject) => {
        web3.eth.getTransactionCount(web3.eth.defaultAccount, (error, result) => {
            if(error) reject(error);
            resolve(web3.utils.toHex(result));
        })
    })
}

const getGasPrice = () => {
    return new Promise((resolve, reject) => {
        web3.eth.getGasPrice((error, result) => {
            if(error) reject(error);
            resolve(web3.utils.toHex(result));
        })
    })
}

// const sendRawTransaction = (rawTx) => {
//     const privateKey = "d05bd152f3d71ff5f91830f3ccc1090fb670c7026ebf8c2136d4e5090d59398d";
//     const tx = new Tx(rawTx);
//     const privateKeyBuffer = Buffer.from(privateKey, 'hex');
//     tx.sign(privateKeyBuffer);
//     const serializedTx = tx.serialize();
//     web3.eth.sendRawTransaction('0x' + serializedTx.toString('hex'), function(err, hash) {
//         console.log('Error:', err);
//         console.log('Hash:', hash);
//     });
// }
  
Promise.all([getNonce(), getGasPrice()]).then(values => {
    // const rawTx = {
    //     to: '0x203D17B4a1725E001426b7Ab3193E6657b0dBcc6',
    //     gasLimit: web3.toHex(1000000),
    //     value: web3.toHex(web3.toWei('0.1', 'ether')),
    //     nonce: values[0],
    //     gasPrice: values[1]
    // };
    // console.log(rawTx);
    // return(rawTx);

       console.log("nonce: %s", web3.utils.hexToNumber(values[0]));
       console.log("GasPrice: %s", web3.utils.hexToNumber(values[1]));

       web3.eth.estimateGas({from: "0x5921a4C1B13afbD4b61d63e9c7BD47741C47B176",data: contractjson.bytecode.object}).then(o=>{console.log("estimateGas: %o", o);})

    web3.eth.sendTransaction({
        from: "0x5921a4C1B13afbD4b61d63e9c7BD47741C47B176", // web3.eth.coinbase,  // web3.eth.getAccounts() 第一筆
        data: certjson.bytecode,
        nonce: values[0],
        gasPrice: values[1],
        gas: 4700000
    }).then(o=>{
        console.log("txhash object: %o", o); 
        TxHash = o.transactionHash;
        console.log("TxHash: %o", TxHash)
    
        web3.eth.getTransactionReceipt(TxHash).then(o=>{
            console.log("check contractAddress object: %s", o.contractAddress); 
        });    
    })
    .catch(e => console.log("sendTransaction error: %o", e));
})
.then(console.log("create transaction ok!"))
.catch(e => console.log("promise all error: %o", e))


node createcontract.js


===========
every 10sec create contract

First: fixed contract



pragma solidity >=0.4.25 <0.7.0;


contract MetaCoin {
 mapping (address => uint) balances;

 event Transfer(address indexed _from, address indexed _to, uint256 _value);

 constructor() public {
  balances[msg.sender] = 10000;
 }

 function sendCoin(address receiver, uint amount) public returns(bool sufficient) {
  if (balances[msg.sender] < amount) return false;
  balances[msg.sender] -= amount;
  balances[receiver] += amount;
  emit Transfer(msg.sender, receiver, amount);
  return true;
 }

 function getBalance(address addr) public view returns(uint) {
  return balances[addr];
 }
}

Promise.all method & web3.eth.sendTransaction


var fs  = require('fs');

var Web3 = require("web3");
var provider = new Web3.providers.HttpProvider("http://192.168.99.100:18545");
var web3 = new Web3(provider);

console.log("before web set account: %o", web3.eth.defaultAccount);
const privateKey = '138cbbfb21686ddc3b5ffeb2cfc83491175af68319977acb81d0ae93392c626c';
const account = web3.eth.accounts.privateKeyToAccount('0x' + privateKey);
web3.eth.accounts.wallet.add(account);
console.log("private key import to account: %o", account.address)
web3.eth.defaultAccount = account.address;

try {
    web3.eth.personal.unlockAccount(account.address, "").then(console.log('Account unlocked!'));
} catch (err) {
    console.error('web3 unlockAccount Error: %o', err);
}

var contractjson;
var contractjsonpath = './MetaCoin.json';

try {
    contractjson = JSON.parse(fs.readFileSync(contractjsonpath));
} catch (err) {
    console.error('readFileSync Error: %o', err);
}

const getNonce = () => {
    return new Promise((resolve, reject) => {
        web3.eth.getTransactionCount(web3.eth.defaultAccount, (error, result) => {
            if(error) reject(error);
            resolve(web3.utils.toHex(result));
        })
    })
}

const getGasPrice = () => {
    return new Promise((resolve, reject) => {
        web3.eth.getGasPrice((error, result) => {
            if(error) reject(error);
            resolve(web3.utils.toHex(result));
        })
    })
}

Promise.all([getNonce(), getGasPrice()]).then(values => {
    console.log("values: Nonce %s  GasPrice %s", web3.utils.hexToNumber(values[0]), web3.utils.hexToNumber(values[1]));
}).then(console.log("create transaction ok!"))
.catch(e => console.log("promise all error: %o", e))

setInterval( () => {

Promise.all([getNonce(), getGasPrice()]).then(values => {
    console.log("nonce: %s", web3.utils.hexToNumber(values[0]));
    console.log("GasPrice: %s", web3.utils.hexToNumber(values[1]));
   
   web3.eth.estimateGas({from: "e79d33e93bd888b35e055f1a12d876354729037b",data: contractjson.bytecode.object}).then(o=>{console.log("estimateGas: %o", o);})

    web3.eth.sendTransaction({
        from: "e79d33e93bd888b35e055f1a12d876354729037b", // web3.eth.coinbase,  // web3.eth.getAccounts() 第一筆
        data: contractjson.bytecode.object,
        nonce: values[0],
        gasPrice: 20000000000, //20,000,000,000
        gas: 181949 //181,949
    }).then(o=>{
        console.log("txhash object: %o", o); 
        TxHash = o.transactionHash;
        console.log("TxHash: %o", TxHash)
    
        web3.eth.getTransactionReceipt(TxHash).then(o=>{
            console.log("check contractAddress object: %s", o.contractAddress); 
        });    
    })
    .catch(e => console.log("sendTransaction error: %o", e.message));
})
.then(console.log("create transaction ok!"))
.catch(e => console.log("promise all error: %o", e.message))

}, Math.random() * 10000);


every 5sec create contract & web3 contract method


var fs  = require('fs');

var Web3 = require("web3");
var provider = new Web3.providers.HttpProvider("http://192.168.99.100:18545");
var web3 = new Web3(provider);

console.log("before web set account: %o", web3.eth.defaultAccount);
const privateKey = '138cbbfb21686ddc3b5ffeb2cfc83491175af68319977acb81d0ae93392c626c';
const account = web3.eth.accounts.privateKeyToAccount('0x' + privateKey);
web3.eth.accounts.wallet.add(account);
console.log("private key import to account: %o", account.address)
web3.eth.defaultAccount = account.address;

try {
    web3.eth.personal.unlockAccount(account.address, "").then(console.log('Account unlocked!'));
} catch (err) {
    console.error('web3 unlockAccount Error: %o', err);
}

var contractjson;
var contractjsonpath = './MetaCoin.json';

try {
    contractjson = JSON.parse(fs.readFileSync(contractjsonpath));
} catch (err) {
    console.error('readFileSync Error: %o', err);
}

setInterval( () => {

contractAddr = "0x46Fac13Ca8398545479bF2DA18133Aa87377b559";
contractfrom = "0xe79d33e93bd888b35e055f1a12d876354729037b";
coinOwnerAddr = "0xe79d33e93bd888b35e055f1a12d876354729037b"
sendCointoAddr = "0x5921a4C1B13afbD4b61d63e9c7BD47741C47B176";

var metacoinContract = new web3.eth.Contract(contractjson.abi, contractAddr);

metaCoinContract.methods.getBalance(coinOwnerAddr).call({
    from: contractfrom,
    gasPrice: 20000000000, //20,000,000,000
    gas: 181949
})
.then(o=>{console.log(coinOwnerAddr+" getBalance: %o", o)});

metaCoinContract.methods.sendCoin(sendCointoAddr, 10).send({
    from: contractfrom,
    gasPrice: 20000000000, //20,000,000,000
    gas: 181949
})
.then(o=>{console.log("sendCoin: %o", o)});

metaCoinContract.methods.getBalance(sendCointoAddr).call({
    from: contractfrom,
    gasPrice: 20000000000, //20,000,000,000
    gas: 181949
})
.then(o=>{console.log(sendCointoAddr+" getBalance: %o", o)});

}, Math.random() * 5000);

// .on('transactionHash', function(transactionHash){
//     console.log("transactionHash: %o", transactionHash)
// })
// .on('receipt', function(receipt){
//     console.log("receipt: %o", receipt)
//     console.log("receipt.contractAddress: %o", receipt.contractAddress) 
// })
// .on('confirmation', function(confirmationNumber, receipt){
//     console.log("confirmationNumber: %o", confirmationNumber)
//     console.log("confirmation receipt: %o", receipt)
// })
// .on('error', function(error){console.log("error: %o", error.message)});


=====
https://medium.com/finnovate-io/how-do-i-sign-transactions-with-web3-f90a853904a2
https://ethereum.stackexchange.com/questions/60611/defining-the-transaction-object-for-offline-transaction-signing-using-web3-js-f
https://github.com/ethereum/web3.js/issues/1430

https://programtheblockchain.com/posts/

Architecture Behind Sila Ethereum Transactions

https://silamoney.com/2019/07/08/using-aws-lambda-sqs-with-web3/
https://silamoney.com/2019/07/08/using-aws-lambda-sqs-with-web3-2/



Major components

  1. DynamoDB to store the nonce associated with ethereum addresses authorized to send ethereum smart contract transactions
  2. Lambda functions triggered by SQS events for SilaToken issuance, redemption, and transfer messages
  3. Ethereum RPC EC2 servers running Parity Ethereum client
  4. AWS Secrets Manager to store private keys being used to sign the transactions
  5. Orchestrator as a bridge between REST API, ACH, and ethereum transactions. Orchestrator is a piece of code that handles the transaction state and reroutes them to right queue.
  6. SQS as an interface between different services like REST API, ACH, Ethereum issuance, redemption, and transfers.


Transaction Lifecycle

Messages for SilaToken issuance, redemption, and transfer comes in through Sila APIs. Dependent on the action (issue, redeem, and transfer), the message is sent to the relevant queue by Orchestrator, which in turn triggers the send transaction Lambda function.
That sends the transaction, signed by Sila’s authorized address, to Ethereum node and increases the nonce in the database by one, for subsequent transactions. The message is deleted from the ethereum transaction queue and sent to the ethereum pending queue with the transaction hash and nonce, then sent with the block number appended in the message history. Replace and check for transaction send failure if there is a bad RPC connection.

play around with sila api

Constructing a Transaction:

constructing transaction

Sending a transaction:

AWS Lambda SQS Fintech

Nonce management

After experimenting with several ways to manage the authorized address nonce we settled on storing it in a database, as it is faster to retrieve and update there than making a Web3 call to the RPC server and waiting for the transaction to be mined. It has its pitfalls, however. For example, subsequent transactions can get stuck until previous transactions have been mined, but that’s why we have three Lambda functions that are watching just the pending transactions — and we’ll discuss how to handle pending ethereum smart contract transactions in the next section.
Nonce management is not as straightforward, as we have three Lambda functions that can send transactions. In our case we have conditions in place that are dependent on message history.

Deciding gas price & gas limit

Gas limit is set based on the amount of computation involved in the smart contract function call. However we can play around with the gas price to make sure transactions are being mined in the desired time. We use a modified version of eth_gas_station engine to decide the gas price, based on the network mining requirements.

Handling Transactions in Pending Queue

Let’s dive deeper into the three Lambda functions that are watching the pending queue . . .

1. Check pending transactions for success or a fail

Previously we discussed how we appended the tx_hash, nonce and sent_at_blockNumber in the message history, we use tx_hash and web3 module to get the transaction status. The transaction status can be 0,1, or null depending on if the transaction has been mined successfully. Status 0 and 1 both result in a nonce increment for the authorized address, as the transaction was mined in some block. If the status is 0, which means the transaction failed, we retry the transaction by sending it back to the transaction queue. Each transaction is restricted to a maximum of 3 retries, after which it is dumped into Orchestrator. If the status is 1 which means that the transaction was successful, a message with success update is sent to Orchestrator.

2. Replacing stuck transactions

If the transaction hash gets a null and transaction has been pending in the node memory pool for a long time, consider how we appended the sent_at_block number and nonce in the message history. We get the current block number, using Web3, and compare the difference; if the difference is more than 80 blocks (and the difference can be set to higher or lower), which means the transaction has been pending for 80 blocks, we replace the transaction with a higher gas price, keeping the nonce value the same as in the message.

3. Handling transaction send failures

If you play with Ethereum long enough you will have certain cases where you are unable to find the sent transaction in the node memory pool. This means the transaction never hit the Ethereum RPC server, but we have another Lambda function that will redirect the transaction message to the queue.

Like this article? Share it with your network!
About Sila
Sila provides Banking and Payments Infrastructure-as-a-Service for teams building the next generation of financial products and services. Our banking API replaces the need for integrating with legacy financial institutions saving you months of development time and thousands in legal and regulatory expenses.

haproxy failover backup server

https://www.haproxy.com/blog/failover-and-worst-case-management-with-haproxy/


Normal backup servers: In this case, s3 will be used first, until it fails, then s4 will be used.



frontent ft_app
 bind 10.0.0.1:80
 default_backend bk_app_main
backend bk_app_main
 server s1 10.0.0.101:80 check
 server s2 10.0.0.102:80 check
 server s3 10.0.0.103:80 check backup
 server s4 10.0.0.104:80 check backup


Multiple backup servers: In this case, both s3 and s4 will be used if they are available.

option allbackups



frontent ft_app
 bind 10.0.0.1:80
 default_backend bk_app_main
backend bk_app_main
 option allbackups
 server s1 10.0.0.101:80 check
 server s2 10.0.0.102:80 check
 server s3 10.0.0.103:80 check backup
 server s4 10.0.0.104:80 check backup

nginx failover without load balancing

https://serverfault.com/questions/480241/nginx-failover-without-load-balancing


pstream backend {
    server 1.2.3.4:80 fail_timeout=5s max_fails=3;
    server 4.5.6.7:80 backup;
}

server {
    listen 80;
    server_name whatevs.com;

    location / {
        proxy_pass http://backend;
    }
}


https://www.cnblogs.com/biglittleant/p/8979887.html

backup 预留的备份服务器,当其他所有的非backup服务器出现故障或者忙的时候,才会请求backup机器,因为这台集群的压力最小。

max_fails 允许请求失败的次数,默认是1,当超过最大次数时,返回proxy_next_upstream模块定义的错误。0表示禁止失败尝试,企业场景:2-3.京东1次,蓝汛10次,根据业务需求去配置。

fail_timeout,在经历了max_fails次失败后,暂停服务的时间。京东是3s,蓝汛是3s,根据业务需求配置。常规业务2-3秒合理。

例:如果max_fails是5,他就检测5次,如果五次都是502.那么,他就会根据fail_timeout 的值,等待10秒,再去检测。


https://blog.51cto.com/wangwei007/1103727

ethereum Nonce collisions

https://hackernoon.com/ethereum-blockchain-in-a-real-project-with-500k-users-f85ee4821b12

Nonce collisions
Nonce collisions were another mysterious thing we’ve encountered when trying to scale the number of Geth nodes in order to cover the case when one node crashes. It turns out that


We used a simple load balancer before the three Geth nodes, which was sending each transaction to one of the three nodes. The problem was that each time we submitted many transactions at once, some of those transactions were mysteriously disappearing. It took a day or two until we finally figured out that this was a problem with nonce collisions.

When you are submitting raw transactions to the network you are fine, because you keep track of nonce numbers yourself. In this case you just need a node to publish raw transactions to the network. But in the case you are using an account unlocking mechanism built into the node and do not specify the nonce when publishing transactions (with web3 or so), the node tries to pick the appropriate nonce value itself and then signs a transaction.

Because of the network delays, in the case two nodes receive the same transaction publishing request, they can generate the same nonce value. At the moment of receiving the transaction publishing request they don’t know that they both received a transaction with the same nonce. Thus, when propagating these transactions through the network, one of them will eventually be dropped because its “transaction nonce is too low”.

To fix nonce collisions introduced by adding a load balancer to a system, we needed to create a different kind of load balancer. For example, a load balancer which always uses one particular node and switches to another node only if the first one is down.

ethereum Proper Transaction Signing nonce

https://ethereum.stackexchange.com/questions/12823/proper-transaction-signing


const Web3 = require('web3');
const Tx = require('ethereumjs-tx');
const config = require('./config');

const web3 = new Web3(new Web3.providers.HttpProvider(config.provider)); //link provided by Infura.io
web3.eth.defaultAccount = "0xc929c890f1398d5c1ecdf4f9ecec016906ac9f7f";

const getNonce = () => {
  return new Promise((resolve, reject) => {
    web3.eth.getTransactionCount(web3.eth.defaultAccount, (error, result) => {
      if(error) reject(error);
      resolve(web3.toHex(result));
    })
  })
}
const getGasPrice = () => {
  return new Promise((resolve, reject) => {
    web3.eth.getGasPrice((error, result) => {
      if(error) reject(error);
      resolve(web3.toHex(result.toNumber()));
    })
  })
}

const sendRawTransaction = (rawTx) => {
  const privateKey = "190b820c2627f26fd1b973b72dcba78ff677ca4395c64a4a2d0f4ef8de36883c";
  const tx = new Tx(rawTx);
  const privateKeyBuffer = Buffer.from(privateKey, 'hex');
  tx.sign(privateKeyBuffer);
  const serializedTx = tx.serialize();
  web3.eth.sendRawTransaction('0x' + serializedTx.toString('hex'), function(err, hash) {
      console.log('Error:', err);
      console.log('Hash:', hash);
  });
}

Promise.all([getNonce(), getGasPrice()])
  .then(values => {
    const rawTx = {
      to: '0x203D17B4a1725E001426b7Ab3193E6657b0dBcc6',
      gasLimit: web3.toHex(1000000),
      value: web3.toHex(web3.toWei('0.1', 'ether')),
      nonce: values[0],
      gasPrice: values[1]
    };
    console.log(rawTx);
    return(rawTx);
  })
  .then(sendRawTransaction)
  .catch(e => console.log(e))

ring buffer

https://zhen.org/blog/ring-buffer-variable-length-low-latency-disruptor-style/

https://github.com/smartystreets-prototypes/go-disruptor

ethereum transaction template

https://ethereum.stackexchange.com/questions/50042/why-does-sendsignedtransaction-return-a-tx-hash-but-does-not-post-to-the-rinkeby


window.web3 = new Web3(new Web3.providers.HttpProvider(endpoint));

sendEther() {
    const fromAccount = **acct1**;
    const toAccount   = **acct2**;

    const rawTransaction    = this.makeRawTransaction(fromAccount, toAccount);
    const signedTransaction = this.makeSignedTransaction(rawTransaction);
    const serializedTransaction = `0x${signedTransaction.serialize().toString('hex')}`;

    window.web3.eth.sendSignedTransaction(serializedTransaction, (error, result) => {
        if(!error) {
          console.log(`Transaction hash is: ${result}`);
          this.setState({
            etherscanUrl: `https://rinkeby.etherscan.io/tx/${result}`,
            error: null
          });

        } else {
          this.setState({ error: error.message })
          console.error(error);
        }
    });
  }

  makeSignedTransaction(rawTransaction) {
    const privateKey   = '**************';
    const privateKeyX  = new Buffer(privateKey, 'hex');
    const transaction  = new EthTx(rawTransaction);
    transaction.sign(privateKeyX);

    return transaction;
  }

  makeRawTransaction(fromAccount, toAccount) {
    const { exchangeRate } = this.props;
    const amount = (1 / exchangeRate) * 5;

    return ({
      nonce: window.web3.utils.toHex(window.web3.eth.getTransactionCount(fromAccount)),
      to: toAccount,
      gasPrice: window.web3.utils.toHex(100000000000),
      gasLimit: window.web3.utils.toHex(100000),
      value: window.web3.utils.toHex(window.web3.utils.toWei(`${amount}`, 'ether')),
      data: ''
    });
  }

[轉]Windows、WSL 与 Linux 的性能对比

https://www.cnbeta.com/articles/tech/922349.htm

尽管执行了各种各样的测试,但是如果对在七个不同操作系统上成功运行的所有测试取几何平均值,可以得出这样的结论:

Windows 10 Build 19008 的总体性能要比 Build 18362 版本好,而 WSL 的性能并没有太大变化

WSL2 比 WSL 的性能确实稍好一些,这是因为在 I/O 或网络活动繁重的工作负载的情况下前者性能要好得多

在这种特殊的 Core i9 7960X 场景下,运行 Ubuntu Linux 的速度总体上比最快的 Windows 配置快 27%

有兴趣的朋友可查看这份更详细的 OpenBenchmarking.org 结果文件,以深入研究这些 Windows / WSL / Linux 基准测试内容。

geth attach



geth --exec "eth.blockNumber" attach --datadir ./
geth --exec "eth.syncing" attach --datadir ./
geth --exec "admin.peers" attach --datadir ./
geth --exec "clique.getSnapshot()" attach --datadir ./

watch -n 2 'geth --exec "clique.getSnapshot()" attach --datadir ./'

geth-prometheus

https://github.com/karalabe/geth-prometheus


https://blog.ethereum.org/2019/07/10/geth-v1-9-0/

You can quickly reproduce the above charts via my clone of Maxim Krasilnikov’s project by running docker-compose up in the repo root and accessing http://localhost:3000 with the admin/admin credentials. Alternatively, you can view my testing snapshot on Raintank, or import this dashboard into your own Grafana instance

源碼掃瞄

Checkmarx
Fortify

ethereum geth check transaction

geth console


## get balance

eth.getTransaction("")
eth.getTransactionReceipt("")

EX: transaction id 0x8dfaa1b5d2e660ee2d3aa9fd0eeb33cc726d50122790e882a914ffd7d02e3a83
eth.getTransaction("0x8dfaa1b5d2e660ee2d3aa9fd0eeb33cc726d50122790e882a914ffd7d02e3a83")
eth.getTransactionReceipt("0x8dfaa1b5d2e660ee2d3aa9fd0eeb33cc726d50122790e882a914ffd7d02e3a83")


## get transaction count

eth.getTransactionCount()
eth.getTransactionCount(, "pending")

EX: transaction id 0x8dfaa1b5d2e660ee2d3aa9fd0eeb33cc726d50122790e882a914ffd7d02e3a83
eth.getTransactionCount("0x8dfaa1b5d2e660ee2d3aa9fd0eeb33cc726d50122790e882a914ffd7d02e3a83")
eth.getTransactionCount("0x8dfaa1b5d2e660ee2d3aa9fd0eeb33cc726d50122790e882a914ffd7d02e3a83", "pending")


## check pending queued

txpool.status

EX:
{
pending: 0,
queued: 5
}

融資

目前好像國泰比較優
年利率2% 手續費2千
一年到期續約不用手續費
這些都是基本條件不需要談

對啊,不過國泰大概是給年薪的3倍額度

年薪50萬,就150萬

聯邦18個月後,要還一次本金嗎?
聯邦不用還本金
國泰也不用


所以500萬,屆滿300萬,18個月後,直接續新約齁?

銀行、證券金融,國泰、聯邦、元大證金,就沒這種規定

查驗 驗收

.需求書內 合約 改成 契約

勞務請購 準備文件
1. 購案核定清單
2. 自我檢核表
3. 報價單
4. 需求書
5. 承攬商 (有派人力到 中心/公司 工作情況)
最後 預估金額分析表 (簽核過財會後,請購人員會給予後填寫)

案子的負責「採購人員」是: AAA
先請試填請購單後,截取畫面併相關文件給採購人員確認是否正確後,再正式填寫請購單
會科問題 BBB 會計人員

金額比例 300 200 (依期數 如這裡500 分二期)
需求書上 兩次:10/30、6/31
付款注意:年底可能會關帳,要提前,建議一個月為主

特別注意:查驗和驗收不同,案子通常第一期為查驗,第二期為驗收,兩者皆為組長(負責主管),如沒空,可找代理人,查驗/驗收需求項目、文件順序需按照需求書

第一期查驗:
.我方需要確認資料、系統和文件是否正確,系統檔案可存放光碟(建議全放)
.查驗文件依需求書需求項目為主,再說明查驗或驗收順序已備齊
.廠商準備現場DEMO及列印文件,務必提前一到二星期準備
.另廠商需寄送EMail告知開發完畢,可進行查驗或驗收,印該EMail代表收到開發完畢文件
.查驗文件上的完成覆約日期為收到EMail為主,查驗測試時間則為實際排定查驗測試日期

第二期驗收:
.需先再跑查驗流程(非第一期查驗),再驗收
.需自行把系統自行跑過一次,代表有實際確認過
.其他同第一期
.查驗過後,將相關資料給予採購人員,會協助安排組長驗收時間,自行安排會議室
.驗收記錄給予廠商,進行發票開立作業
.收到廠商發票後交給採購人員

[轉]Flutter 状态管理指南之 Provider

https://zhuanlan.zhihu.com/p/70280813

[轉]Flutter 全局状态管理之 Provider 初探

https://juejin.im/post/5d8f324ee51d45781e0f5dca

一、什么是全局状态管理

当我们在使用 Flutter 进行应用开发时,可能需要不同的页面共享应用或者说变量的状态,当这个状态发生改变时,所有依赖这个状态的 ui 都会随之发生改变。在同一个页面中还好说,直接通过 setState 就可以达到目的,要是不同的页面呢,或者当应用变得非常复杂,页面非常多的时候,这个时候全局状态管理就显得非常重要了。
在 Flutter 中,状态管理可以有如下几种方式:
1、setState
flutter 中最简单使 ui 根据状态发生改变的方式。
2、 InheritedWidget & InheritedModel
InheritedWidget 和 InheritedModel 是 flutter 原生提供的状态管理解决方案。 当InheritedWidget发生变化时,它的子树中所有依赖了它的数据的Widget都会进行rebuild,这使得开发者省去了维护数据同步逻辑的麻烦。
3、Provider & Scoped Model
Provider 与 Scoped Model 都属于第三方库,两者使用起来差不多,其中 Provider 是 Google I/O 2019 大会上官方推荐的状态管理方式。
4、Redux
在 Redux 状态管理中,所有的状态都储存在Store里,Flutter 中的 Widget 会根据这个 Store 去渲染视图,而状态的改变也是通过 Reduex 里面的 action 来进行的。
5、BLoC / Rx
BLoC的全称是 业务逻辑组件(Business Logic Component)。就是用reactive programming方式构建应用,一个由流构成的完全异步的世界。 BLoc 可以看作是 Flutter 中的异步事件总线,当然在除了 BLoc 外,Flutter 中有专门的响应式编程库,就是RxDart,RxDart是基于ReactiveX标准API的Dart版本实现,由Dart标准库中Stream扩展而成。

作者:Flutter编程开发
链接:https://juejin.im/post/5d8f324ee51d45781e0f5dca
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

[轉]如何選擇ERP

https://www.ptt.cc/bbs/MIS/M.1575624725.A.74A.html

: 各位前輩大家好
: 小弟目前被賦予任務如下:
: 評估各家ERP優缺並負責導入相關事宜
: 我司產業為製造業(女鞋代工),產品皆外銷
: 主要需要解決的問題為以下:
: 1.BOM數位化問題
: 2.訂單轉換採購單,備料單重工問題
: 預算目前沒有上限;
: 從未導入過任何ERP系統,截至目前為止皆為人工手KEY各種報表;
: 目前已接觸過鼎新,尚揚,鴻來軟件
: 請問各位前輩還有推薦的ERP廠商嗎?

原提問人已經「面談」過不少軟體商的業務人員,為何還來這裡徵求各界意見?

其實,聽取軟體商簡報後,仍陷入「一頭霧水」狀態的MIS主管,我曾經就是其中一員,彼岸更多!

這個提問觸發我寫下一篇文章《如何選擇ERP》。先預熱一下...

恰巧我曾經任職一家只幫愛迪達代工,18000人的廣東鞋廠,厚顏擔任只出一張嘴「管理」28名部屬的MIS部門最高主管(經理)。

該廠當時:廣東有相距近百公里之遙的2個工廠、臺中辦公室、積極動工中的印度工廠。

除了HR當然有的考勤、薪資業務之外,有員工(收費、補助)餐廳、保險、住宿...等資訊需求。

入職當時,該廠正積極汰換ERP軟體,鄙人立即展開「ERP選型」工作。

接手之前,已經有下列軟體商爭取那門生意:

- SAP的「鞋服solution」
- 金蝶
- 深圳的中X(老闆已改行,偶有聯絡。)
- 高雄的先濬

我的調查方式:製作問卷,列舉技術問題,邀請軟體商答題。

按我的記憶列舉一、二:

1. 軟體能否「同時」處理「品名」和「尺碼」?所謂「處理」,包括:跑MRP、追蹤和紀錄各「品名」和「尺碼」的成本與數量。

2. 軟體能否處理各材料的保稅(出口退稅)功能?

3. 軟體能否線上切換語系?(希望印度廠也能使用)

4. 資訊人員能否設計一份報表,中國廠職員使用簡體字打印、臺中廠職員使用正體字打印、印度職員使用英文打印?

5. 資訊人員每設計一份報表之後,是否必須分別在中國廠的800部電腦安裝、去印度廠安裝、去臺中辦公室安裝?(「安裝」包括遠程分發、自動下載並安裝package)

6. 軟體系統使用何種程式語言設計?(事涉MIS人員接手維護軟體的學習曲線、求才難易度、薪資水準)

7. 軟體使用何種資料庫管理系統?(影響老闆的錢包)

8. 會計月結,是否必須來回嘗試幾次過帳、反過帳、結帳、反結帳,可能失敗、出現「負庫存量」、「負金額」?

9. 軟體能否「隨時」顯示「品名」和「尺碼」的真實(不是「標準」)成本與數量,無須等到下月初的月結?

...

當時,

- 用過Tiptop,確定0分,所以懶得聯絡鼎新業務員。
- 知道SAP是垃圾,故直接忽略SAP,連問卷也不發給那些X子。
- 金蝶不繳交問卷,從此失聯。
- 中X答非所問、回答不完整,但是仍拜訪、打電話,積極爭取訂單。
- 先濬拒絕答題。

我當時最敬佩的軟體商是金蝶,因為他們躲起來,證明是唯一有羞恥心的業務員,他們不願意欺騙、說謊。

老闆無視我的反對,所以先濬拿到訂單。我離職後,老闆支付三分之一合約金(330萬元臺幣)後,先濬從此失聯。

我給原提問人能心安理得、睡好覺的建議:

1、參考我前述問卷內容以及下面的參考資料,製作一份問卷,發給全部軟體商,邀請他們答題。

2、邀請那些全部回答「yes」的廠商向你當面示範那些「yes」的軟體功能。

3、淘汰這些軟體商:回答不清楚、回答「no」、不敢示範那些「yes」的軟體功能。

4、從那些全部回答「yes」而且確實示範軟體功能真實不虛的軟體商之中,選擇報價最低的一家,直接推薦給老闆。

5、如果不幸證明全部檯面上的軟體商都是騙子的話,只好去我的SaaS官網免費註冊、試用,基於你的專業和敬業,回答你自己的問卷,並且相信自己的眼睛,而非耳朵。
手冊:https://terarows.gitlab.io/app2/

---參考資料---

http://www.itpub.net/thread-1892471-1-1.html

- 勞工:三班制:07:00 ~ 15:00、15:00 ~ 23:00、23:00 ~ 07:00。夜班提供夜點費。
- 遲到半小時內,扣薪N元。遲到M小時以上,視同請假半日。早退,(忘了詳情!)。未請假,曠職,扣薪X元。
- 有全勤獎。
- 小過:扣N元;大過,扣M元。小功:獎N元;大功,獎M元。
- 文員:高級主管不打卡,其餘須打卡。可填單報出差。
- 薪資:按層級表。也許有年終獎金。
- 年假/年資對照表。
- 外國勞工提供住宿。
- 中國廠有用餐制度、住房、保險。
- 台灣廠有勞保、健保、綜合所得扣繳憑單。
- 當然,打卡鐘24小時侍候。

多公司。在線切換,無須登出再登錄。

多國語言。在線切換,無須登出再登錄。

已翻譯正體中文、簡體中文、英文。按各種語言輸入料項目、供應商名、地址、人名..。

多時區。倫敦用戶輸入、顯示「2014-12-01 00:00:00 +0」,北京用戶輸入、顯示「2014-12-01
08:00:00 +8」。

支持料品批號、鞋子的尺碼、成衣的尺碼。

會計科目只有一段。
一些ERP要求:每一個料號指定一個多段會計科目編碼。例如:1111-00A-123。其中,「1111」代表『原料』、「00A」代表『00A部門』、「123」代表『123料號』。
PostERP只使用會計科目只有一段:「1111」,代表『原料』。

無縫整合會計:凡是與金額相關的交易,都轉拋會計分錄。會計人員的記帳工作趨近零。

會計分錄只有一個屏幕,無須多個屏幕來回翻找、比對、輸入。這個屏幕容納成本、供應商、客戶、應收帳款、應付帳款、銀行存摺帳號...等信息。

無須過帳、反過帳。結帳重點工作,只運行一個指令,處理:虛帳戶結轉實帳戶、本期實帳戶餘額復制成下期期初餘額。

支持先進先出、後進先出、移動加權平均成本。永續盤存制。

隨時反應每一個倉位中的每一個項目、每一個批號的最新成本,無須等到月結。

MRP同時考慮項目與批號(或尺碼):
1、需求數量(數量,時間)
2、倉庫現存可用量(數量)
3、BOM標準用量(數量)
4、BOM父項損耗率、子項損耗率(數量)
5、生產工藝(數量、時間)(目前從缺)
6、計劃單數量(數量,時間)
7、請購單數量(數量,時間)
8、採購單數量(數量,時間)
9、外包單數量(數量,時間)
10、生產單數量(數量,時間)
11、生產投料單數量(數量,時間)
12、生產記錄(數量、時間)
13、最小包裝量/不可分割數量(數量)
14、最低採購數量(數量)
15、最低生產批量/最低外包批量(數量)
16、時柵(時間)(目前從缺)
17、時格(時間)(目前從缺)
18、提前期(時間)

多層「一對多」單據。例如:在同一個屏幕的一張出貨單號含多種藥名,每個藥名含多個批號,每個批號含多個出貨日期,每個出貨日期含多個交貨目的地;自多個儲位撿貨。

各種語言在線求助:屏幕說明、字段說明、報表用途與參數說明、程序用途與參數說明。

備正體中文、簡體中文、英文文檔,供使用人以瀏覽器閱讀。

MIS人員在瘦客戶上面開發、修改、強化ERP,終端使用人在瘦客戶操作ERP。

瘦客戶內建報表引擎,無須外掛Crystal Report等:MIS人員設計報表樣板,終端使用人運行報表。100%整合在瘦客戶的menu中。

MIS人員設計的一份WYSIWYG報表樣板,台灣文員預覽或打印正體中文報表、中國廠員工人打印正體中文報表、印度user print英文report。可設計cross tab報表、含bar code報表、子報表(sub-report)。

伺服器軟件與瘦客戶之間的傳輸資料經過(1)加密(2)壓縮。不需要VPN、Citrix、Windows Remote Desktop。

提供類似Unix crontab的排程機制。

巨細靡遺記錄user的輸入、修改、刪除記錄。

每一筆記錄都允許附掛32767個文檔,例如:工程圖.png、標準作業程序說明.doc。

屏幕中的每一個table都允許匯出成文檔,供LibreOffice的Calc、M$ Excel等軟件匯入。



《不易聽到SAP專案失敗的原因》:
https://bit.ly/2DPkDZZ
https://bit.ly/2OOanYv

ethereum 交易 驗證

https://www.blocktempo.com/blockchain-technical-overview-structure-of-blockchain-ethereum/

3. 以私鑰簽署交易。
4. 廣播「加上簽名的交易封包」至鄰近的以太坊節點們。


https://ithelp.ithome.com.tw/m/articles/10215095

總而言之在區塊鏈接納這筆交易前,先試著用地址反推回原本的公鑰,再用公鑰解密當初這筆交易紀錄的簽章看看,如果公鑰解的開就可以代表是公鑰持有人本人所簽核的,這便是剛剛提到的"數位簽章"。
注意:這段比較像是一般加解密的方式,好像不是ethereum


https://ethereum.stackexchange.com/questions/13778/get-public-key-of-any-ethereum-account

ethereum 簽完的東西 可以 找出 public key
有public key 就可以知道是誰發出這個交易


https://zhuanlan.zhihu.com/p/30481292

签名完成了,我们如何验证某些签名后的数据是哪个账户签名的呢?在web3.js 发布1.0版本以前,验证签名只能通过智能合约的ecrecover函数来实现。新版的web3.js提供了web3.eth.accounts.recover函数用于验证签名。这里我们仍然使用传统的智能合约ecrecover方式。

ecrecover接收数据的哈希值以及r/s/v等参数作为输入,返回实施该签名的账户地址。因此我们只需要通过合约拿到实施签名的地址,和我们真正的地址进行对比,如果地址一致,就说明验证通过了。


這也是ethereum private key和address比較重要的原因了


https://learnblockchain.cn/books/geth/part3/sign-and-valid.html

linux .bashrc


# General Aliases
    alias apk='apk --progress'
    alias ll="ls -ltan"

    alias hosts='cat /etc/hosts'
    alias ..="cd .."
    alias ...="cd ../.."
    alias ....="cd ../../.."
    alias untar="tar xzvkf"
    alias mv="mv -nv"
    alias cp="cp -i"
    alias ip4="ip -4 addr"
    alias ip6="ip -6 addr"

    COL_YEL="\[\e[1;33m\]"
    COL_GRA="\[\e[0;37m\]"
    COL_WHI="\[\e[1;37m\]"
    COL_GRE="\[\e[1;32m\]"
    COL_RED="\[\e[1;31m\]"

    # Bash Prompt
    if test "$UID" -eq 0 ; then
        _COL_USER=$COL_RED
        _p=" #"
    else
        _COL_USER=$COL_GRE 
        _p=">"
    fi
    COLORIZED_PROMPT="${_COL_USER}\u${COL_WHI}@${COL_YEL}\h${COL_WHI}:\w${_p} \[\e[m\]"
    case $TERM in
        *term | rxvt | screen )
            PS1="${COLORIZED_PROMPT}\[\e]0;\u@\h:\w\007\]" ;;
        linux )
            PS1="${COLORIZED_PROMPT}" ;;
        * ) 
            PS1="\u@\h:\w${_p} " ;;
    esac

存股

https://www.youtube.com/watch?v=uqlUFvkyEUg

1. 折舊長 不能折舊短 代表長期經營
2. 能控制供應 多或少,像蘋果 有強大的控制供應能力,需求多不見得
3. 產品周期長

hyperledger leader peer endorsing peer committing peer

leader peer 是peer之間動態選舉選出的

endorsing peer 預設為每個peer都是,安裝chaincode後,實例化設定policy可以有變化

committing peer 預設為每個peer都是

https://medium.com/@kctheservant/transactions-in-hyperledger-fabric-50e068dda8a9
https://stackoverflow.com/questions/52893818/difference-between-endorsing-peer-and-committing-peer-in-hyperledger-fabric/52894994

kubernetes K3s Failed!

Failed reason: Node port range can't fixed!


K3s


##### install #####
curl -sfL https://get.k3s.io | sh -


##### login https://192.168.99.119:6443/ get username/password #####
more /etc/rancher/k3s/k3s.yaml


##### change node-port range #####
k3s server --kube-apiserver-arg --service-node-port-range=1-65535


##### install dashboard #####
k3s kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v1.10.1/src/deploy/recommended/kubernetes-dashboard.yaml --insecure-skip-tls-verify

k3s kubectl create secret generic kubernetes-dashboard-certs --from-file=certs -n kube-system

k3s kubectl apply -f dashboard-ClusterRoleBinding.yaml
k3s kubectl apply -f dashboard-adminuser.yaml
k3s kubectl -n kube-system describe secret $(kubectl -n kube-system get secret | grep admin-user | awk '{print $1}')

Find admin-user-token

https://192.168.99.119:30393/


##### kill all #####
k3s-killall.sh
k3s-uninstall.sh

##### start k3s service #####
service k3s status ## check k3s is stop
service k3s start

Replace uglifyjs-webpack-plugin with terser-webpack-plugin

https://github.com/vuejs/vue-cli/issues/2245

https://github.com/webpack-contrib/terser-webpack-plugin

https://stackoverflow.com/questions/57360588/how-to-use-terser-with-webpack

https://juejin.im/post/5cbc40ea6fb9a068b65e2aa6


npm install npm install terser-webpack-plugin

vue.config.js


const TerserPlugin = require('terser-webpack-plugin');

module.exports = {
    chainWebpack: process.env.NODE_ENV === 'production'
    ? config => {
        config.module.rules.delete('eslint');
        config.optimization.minimizer([
            new TerserPlugin({
                terserOptions: {
                    parse: {
                      ecma: 8
                    },
                    compress: {
                      ecma       : 5,
                      warnings   : false,
                      comparisons: false,
                      inline     : 2
                    },
                    mangle: {
                      reserved: ["BigInteger","ECPair","Point"],
                      safari10: true
                    },
                    output: {
                      ecma      : 5,
                      comments  : false,
                      ascii_only: true
                    }
                },
                cache: true,
                parallel: true,
                sourceMap: false, // false 可以減少一半的js大小,sourceMap為除錯使用
            })
        ]);
    }
    : config => {
        config.module.rules.delete('eslint');
    },
    devServer: {
        host: '0.0.0.0',
        port: '80',
        //public: '0.0.0.0:80',  //無效
        disableHostCheck: true,
    }
}

[轉]Kubernetes 调整 nodePort 端口范围

https://qhh.me/2019/08/pod 文件定义在 /etc/kubernetes/manifests/kube-apiserver.yaml15/Kubernetes-%E8%B0%83%E6%95%B4-nodePort-%E7%AB%AF%E5%8F%A3%E8%8C%83%E5%9B%B4/

在 command 下添加 --service-node-port-range=1-65535 参数,修改后会自动生效,无需其他操作:



apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    component: kube-apiserver
    tier: control-plane
  name: kube-apiserver
  namespace: kube-system
spec:
  containers:
  - command:
    - kube-apiserver
    - --service-node-port-range=1-65535
    - --advertise-address=192.168.26.10
    - --allow-privileged=true
    - --authorization-mode=Node,RBAC
    - --client-ca-file=/etc/kubernetes/pki/ca.crt
    - --enable-admission-plugins=NodeRestriction
    - --enable-bootstrap-token-auth=true
    - --etcd-cafile=/etc/kubernetes/pki/etcd/ca.crt
    - --etcd-certfile=/etc/kubernetes/pki/apiserver-etcd-client.crt
    - --etcd-keyfile=/etc/kubernetes/pki/apiserver-etcd-client.key
    - --etcd-servers=https://127.0.0.1:2379
    - --insecure-port=0
    - --kubelet-client-certificate=/etc/kubernetes/pki/apiserver-kubelet-client.crt
    - --kubelet-client-key=/etc/kubernetes/pki/apiserver-kubelet-client.key
    - --kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname
    - --proxy-client-cert-file=/etc/kubernetes/pki/front-proxy-client.crt
    - --proxy-client-key-file=/etc/kubernetes/pki/front-proxy-client.key
    - --requestheader-allowed-names=front-proxy-client
    - --requestheader-client-ca-file=/etc/kubernetes/pki/front-proxy-ca.crt
    - --requestheader-extra-headers-prefix=X-Remote-Extra-
    - --requestheader-group-headers=X-Remote-Group
    - --requestheader-username-headers=X-Remote-User
    - --secure-port=6443
    - --service-account-key-file=/etc/kubernetes/pki/sa.pub
    - --service-cluster-ip-range=10.96.0.0/12
    - --tls-cert-file=/etc/kubernetes/pki/apiserver.crt
    - --tls-private-key-file=/etc/kubernetes/pki/apiserver.key
    image: registry.aliyuncs.com/google_containers/kube-apiserver:v1.15.2
    imagePullPolicy: IfNotPresent
    livenessProbe:
      failureThreshold: 8
      httpGet:
        host: 192.168.26.10
        path: /healthz
        port: 6443
        scheme: HTTPS
      initialDelaySeconds: 15
      timeoutSeconds: 15
    name: kube-apiserver
    resources:
      requests:
        cpu: 250m
    volumeMounts:
    - mountPath: /etc/ssl/certs
      name: ca-certs
      readOnly: true
    - mountPath: /etc/pki
      name: etc-pki
      readOnly: true
    - mountPath: /etc/kubernetes/pki
      name: k8s-certs
      readOnly: true
  hostNetwork: true
  priorityClassName: system-cluster-critical
  volumes:
  - hostPath:
      path: /etc/ssl/certs
      type: DirectoryOrCreate
    name: ca-certs
  - hostPath:
      path: /etc/pki
      type: DirectoryOrCreate
    name: etc-pki
  - hostPath:
      path: /etc/kubernetes/pki
      type: DirectoryOrCreate
    name: k8s-certs
status: {}

k8s kubernetes Lesson 8 Error

Error: User "system:serviceaccount:kube-system:default" cannot get resource "namespaces"


https://github.com/fnproject/fn-helm/issues/21#issuecomment-545317241


kubectl create serviceaccount --namespace kube-system tiller
kubectl create clusterrolebinding tiller-cluster-rule --clusterrole=cluster-admin --serviceaccount=kube-system:tiller
kubectl patch deploy --namespace kube-system tiller-deploy -p '{"spec":{"template":{"spec":{"serviceAccount":"tiller"}}}}'
helm init --upgrade --service-account tiller

docker registry Other Way


On root home

openssl req -nodes -newkey rsa:4096 -keyout certs/docker-registry.key -out certs/docker-registry.csr -subj "/C=/ST=/L=/O=/OU=/CN=docker-registry"
openssl x509 -req -sha256 -days 365 -in certs/docker-registry.csr -signkey certs/docker-registry.key -out certs/docker-registry.crt


docker run -dp 5000:5000 --name registry -v "$(pwd)"/certs:/certs \
-e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/docker-registry.crt \
-e REGISTRY_HTTP_TLS_KEY=/certs/docker-registry.key \
registry


nano /etc/hosts 
> 192.168.99.118 docker-registry

cd /etc/docker
mkdir certs.d
cd certs.d
mkdir docker-registry:5000
cd docker-registry:5000
cp ~/certs/docker-registry.crt ca.crt

===== check registry is working
docker image pull busybox
docker image tag busybox docker-registry:5000/mybusybox
docker image push docker-registry:5000/mybusybox
docker run --rm docker-registry:5000/mybusybox echo "Hello from busybox"

//
docker rmi busybox docker-registry:5000/mybusybox
docker run --rm docker-registry:5000/mybusybox echo "Hello from busybox"

===== remove registry
docker container stop registry && docker container rm -v registry



https://jkzhao.github.io/2017/09/01/Registry%E7%A7%81%E6%9C%89%E4%BB%93%E5%BA%93%E6%90%AD%E5%BB%BA%E5%8F%8A%E8%AE%A4%E8%AF%81/

列出私有仓库中的所有镜像

curl -k -X GET https://docker-registry:5000/v2/_catalog  >> {"repositories":["mybusybox"]}

curl --cacert certs/docker-registry.crt https://docker-registry:5000/v2/_catalog

curl -k https://docker-registry:5000/v2/_catalog